Problem Statement
Neo Bank of India (a fictional bank) receives a lot of requests for its various finance offerings that include housing loans, two-wheeler loans, real estate financing, and microloans. The number of applications received is something that varies a lot with the season. Going through these applications is a manual and tedious process.
Accurately forecasting the number of cases received can help with resource and manpower management resulting in quick response on applications and more efficient processing. You have been appointed with the task of forecasting daily cases for the next 1 month for 2 different business segments aggregated at the country level keeping in consideration the following major Indian festivals (inclusive but not exhaustive list): Diwali, Dussehra, Ganesh Chaturthi, Navratri, Holi, etc.
Data
The dataset is divided into 2 components, namely train data and test data. The training data consists of dependent variables such as date of application (application_date), business segment (segment 1 or 2), anonymized id for a branch at which application was received (branch_id), State in which application was received (state), zone of state in which application was received (zone). The target variable here is the number of cases/applications received (no_of_applicants).
The test data consists of a unique id for each sample in the test set (id), Date of application (application_date), business segment (segment).
Sample submission consists of id with the number of applicants forecasted for next month for business segments 1 and 2.
Evaluation Metrics
Evaluation for the given case is MAPE - Mean Absolute Percentage Error
Data Preprocessing
In the given data as a part of pre-processing we divide the data based on the business segments to analyze them individually for the missing values we use Interpolation to fill in the missing values.We combined the dataset with Holiday dataset downloaded from Kaggle through left join. This final dataset is used for further analysis. The Holiday dataset consists of all the Indian holidays for a period of 2017 to 2019.The data type of the Application date is also modified to ‘datetime’ type and the dataframes for indovidual segments are converted to ‘tsibble’ object for time series analysis.
Exploratory Data Analysis
Overall we observe that the data from the period 2017 to 2019 tends to be seasonal with peaks during the mid-months.The number of applicants in 2017 and early 2019 tend to be comparatively low and inconsistent with the trend observed during the late-2017 and the year 2018, this may be due to the recovery from the demonetization in November-2016.This inconsistent data may lead to noise while forecasting. On dividing based on segments
We observe that majority of the applications belong to Segment 1 and the zone to receive highest number of applications is the East zone. It is observed that the state of Maharashtra has highest number of application across is branches from 2017-2019.
segment_count_plot
zone_count_plot
data_grpp<-train %>% group_by(application_date,segment) %>%
summarise(no_of_applicants_sum = mean(no_of_applicants))
`summarise()` has grouped output by 'application_date'. You can override using the `.groups` argument.
View(data_grpp)
#Filter data frames based on segment, then convert them into tsibble for segment 1
data_11<-data_grpp %>% filter(segment %in% c(1))
data_11<-data_11 %>%mutate(application_date = as.Date(application_date)) %>%
as_tsibble(index = application_date)
Checking for seasonality, trend and cycles
The below graph shows the number of application against the time period between 2017-19 under segment 1.We notice that the data tends to be stationary with outliers in the region between 2017-2018.Though this a visual conclusion the hypothesis can be validated by testing for stationarity using the ADF(Augmented Dicker-Fuller)Test. Between the period 2017-2018 we observe a linear trend in number of applications received.The trend doesn’t persist for a long time since there is a sudden deceleration in the number of applications during April to May-2018. The applications received follows a cyclical pattern which are usually generated by the autoregressive structure of the series.
Don't know how to automatically pick scale for object of type ts. Defaulting to continuous.

data_1%>%
gg_season(no_of_applicants_sum, period="year") +
labs(y = "Total number of applications",
title = "Yearly Seasonal plot: Number of applications in Neo bank")
Don't know how to automatically pick scale for object of type ts. Defaulting to continuous.

Compared to the Segment 1 , the number of applications received under Segment 2 are most consistent over the given periods and it follows strict cyclical pattern.We observe a monthly seasonality with highest number of applicants during the middle of the months.
autoplot(data_2, no_of_applicants_sum) +
labs(y = "Total number of applications",
title = "Number of applications in Neo bank for Segment 2")
Don't know how to automatically pick scale for object of type ts. Defaulting to continuous.

# b) Yearly seasonality
train_ts %>%
gg_season(no_of_applicants, period="year") +
labs(y = "Total number of applications",
title = "Yearly Seasonal plot: Number of applications in Neo bank")
data_2%>%
gg_season(no_of_applicants_sum, period="year") +
labs(y = "Total number of applications",
title = "Yearly Seasonal plot: Number of applications in Neo bank")
Don't know how to automatically pick scale for object of type ts. Defaulting to continuous.

The above graph shows the cyclical nature of the data across the months for 2017 to 2019.
# # 3. Seasonal sub series plots
#
# options(repr.plot.width=57 ,repr.plot.height= 10)
# data_1 %>%
# gg_subseries(no_of_applicants_sum) +
# labs(
# y = "Total number of applications",
# title = "Number of applications in Neo bank"
# )
#Segment+ Zone
ggplot(Segment1, aes(x = application_date, y = no_of_applicants)) +
geom_line() +
facet_wrap( ~ segment + zone, scales = "free_y", ncol = 5)+
theme(axis.text.x=element_text(angle=90))

From the data we observe the key region for maximum no.of applications North for the future where the bank may expect higher applications.
# data_2 %>%
# gg_subseries(no_of_applicants_sum) +
# labs(
# y = "Total number of applications",
# title = "Number of applications in Neo bank"
# )
month_summary <-Segment1 %>%
group_by(Month) %>%
summarise(no_of_applicants= sum(no_of_applicants),.groups='drop')
month_summary %>%
ggplot(aes(x = reorder(Month, no_of_applicants), y = no_of_applicants, fill = Month)) +
geom_col() +
scale_fill_hp_d(option = "RonWeasley") +
scale_fill_brewer(palette = "Set3") +
scale_y_continuous(limits = c(0, 300000), expand = c(0,0)) +
labs(title = "Total number of applicants in each month", x = "Month", y = "Total applicants") +
theme_classic()
Scale for 'fill' is already present. Adding another scale for 'fill', which will replace the existing scale.

We observe that the bank receives the highest number of applications in October across the three years. Though may vary region wise and state wise.We observe maximum banking activity starting from end of the financial year.
data%>%
pivot_wider(values_from=no_of_applicants, names_from=state)%>%
GGally::ggpairs(columns = 2:9)
5. Lag plots
COMPONENTS OF THE TIME SERIES FOR EACH SEGMENT
We attempt to analyze three main components of the time series to analyze how they behave over time-
Seasonal Component
Trend Cycle Component
Remainder Component
SEGMENT1
For Segment 1 we observe a linear trend from the time period 2017 to 2019.There is an inconsistent yearly seasonality since the gaps are wide at certain points.Throughout the year we see outliers mainly in the Quarter 3.The yearly seasonality shows that the peak business period to be mainly in the months of August-September-October-November for Segment 1 customers.The residual part removes the residual and trend component from the data and seasonally adjusted data shows a variation in the number of application received thus the seasonality plays a major role in the business problem under consideration for Segment 1 customers.

SEGMENT 2
components(dcmp) %>% autoplot()

On decomposing the data under Segment 2 we observe that there is a monthly seasonality we observe through out the years. The weekly seasonality is also significant since the gaps are neither close by nor wide. The trend that we observe is mostly horizontal through each year and tends to have a long term upward trend from 2017 through 2018 from 2018 we observe a downward trend.On removing the seasonality and trend the seasonally adjusted data shows more number of changing levels/points.
CHOICE OF MODELS
ACF and PACF plots
If the autocorrelation plot of acf crosses the dashed blue line, it means that specific lag is significantly correlated with current series.
From here, we can observe that there is approx peak at 0,30,60,90… lags. The maximum at lag 0,30,60.. indicates a positive relationship with monthly cycle.
Here, instead of tailing-off if there is a slow decay we can say it to be a non- stationary series. Examining ACF and PACF helps us to estimate plausible models and select p,d and q. Differencing may be needed if there is slow- decay in the ACF. Several models may need to be estimated. So, here we will try out different combinations of p,d and q to get model with lower AIC or BIC score. AIC and BIC are two measures of goodness of fit. They measure the trade-off between model fit and complexity of data. A lower AIC or BIC value indicates a better fit.
#install.packages('patchwork')
library(patchwork)
a+ b +c +d

#TSLM Modeling
TSLM modeling: In this case the model function is TSLM() (time series linear model), the response variable is no_of_applicants and it is being modeled using trend() (a “special” function specifying a linear trend when it is used within TSLM()). First of all linear model on segment 1 is applied.

Here, we can observe approx value of future predictions for next 30 days.
Next, same process is applied on segment 2 dataset, and approx number of applicants is observed.

From here, we can observe approx values of number of applicants for next 30 days for segment 2. Each row corresponds to one forecast period for each day. The no_of_applicants column contains the forecast distribution, while the .mean column contains the point forecast. The point forecast is the mean (or average) of the forecast distribution.
Warning in file(file, ifelse(append, "a", "w")) :
cannot open file 'C:\Users\asus\Desktop\College\3rd semester\Time series-Akhileshwar\tslm_final1.csv': No such file or directory
Error in file(file, ifelse(append, "a", "w")) :
cannot open the connection
Finally, we combine dataset for next 30 days for segment 1 and 2.
Dickey fuller test
Error in adf.test(data_1$no_of_applicants_sum) :
could not find function "adf.test"
Here, null hypothesis is that time series is not stationary.If null hypothesis is rejected, then target variable is stationary. If it’s not rejected, we should do differencing and then perform dickey-fuller test again. Here, p-value is less than 0.05, so we can reject null hypothesis and say that series is stationary enough to do any kind of time series modeling.
#AR In order to fit the AR model, we have initially converted the number of applicants column to a vector. To see the lag value to be used in the AR model, we have used the above function that has given a value of 7. Hence, we fit a AR(7) model.
Using the predict function, the total number of applications for the next 30 days is forecasted. The (7,0,0) component in arima function is same as fitting a 7th order Autoregressive model. The AIC score for segment 1 data is equal to
AIC(seg1_ar)
[1] 7307.939
The steps are similarly followed for segment 2 data as well. The AIC score for Segment 2 is found to be
[1] 11576.89
Arima Modeling
While exponential smoothing models are based on a description of the trend and seasonality in the data, ARIMA models aim to describe the autocorrelations in the data. White noise describes the assumption that each element in a series is a random draw from a population with zero mean and constant variance. Autoregressive(AR) and moving average(MA) models correct for violations of this white noise assumption.
As our model satisfies stationarity, we move on to applying arima modeling on it. ## Applying arima modeling on segment 1
Series: no_of_applicants_sum
Model: ARIMA(0,1,3)(0,0,2)[7]
Coefficients:
ma1 ma2 ma3 sma1 sma2
-0.7880 -0.1167 -0.0560 0.0630 0.0853
s.e. 0.0353 0.0466 0.0362 0.0369 0.0332
sigma^2 estimated as 548.5: log likelihood=-3633.84
AIC=7279.69 AICc=7279.79 BIC=7307.76

Applying arima modeling on segment 2
Series: no_of_applicants_sum
Model: ARIMA(0,1,0)(0,0,1)[7]
Coefficients:
sma1
0.3526
s.e. 0.0341
sigma^2 estimated as 83552: log likelihood=-5760.52
AIC=11525.04 AICc=11525.05 BIC=11534.44

Here, we observe that we get better predictions from ARIMA than we got from TSLM model. This can be observed from plots as well.
ARIMA (Without seasonality)
Though we got our data as stationary, but plots appeared to have some sort of seasonality. So, we went ahead to use arima by removing seasonality. In segment 1
Series: no_of_applicants_sum
Model: ARIMA(1,1,1)
Coefficients:
ar1 ma1
0.1892 -0.9535
s.e. 0.0384 0.0142
sigma^2 estimated as 513.8: log likelihood=-3609.18
AIC=7224.35 AICc=7224.38 BIC=7238.39
Here, we observe that AIC and BIC value decreases, which shows that this is a better model if we remove seasonality.

Removing seasonality from segment 2
Series: no_of_applicants_sum
Model: ARIMA(1,1,1)(0,0,2)[7]
Coefficients:
ar1 ma1 sma1 sma2
-0.0446 0.0823 0.0615 -0.2470
s.e. 0.4993 0.4949 0.0330 0.0301
sigma^2 estimated as 63097: log likelihood=-5644.87
AIC=11299.74 AICc=11299.82 BIC=11323.24
Here, we observe that AIC and BIC value both decreases when we remove seasonality from data, which shows that this is a better model.

Checking for Trend in data
First off, I’d take the difference of time series to de-trend it, it has a considerable stochastic trend. The most obvious sign of this, beside the time series having a steady upward rise, is that the ACF components takes a long time to die out. While we can fit a model to the data as is with a drift term, it’s much easier to read the ACF and PACF plots when the trend isn’t there. So, we also tried to overcome presence of small amount of trend by two methods(differencing and removing trend component from stl decomposition as well).
Data after differencing
Here, we try to observe ACF and PACF model after differencing.



Warning: Removed 1 row(s) containing missing values (geom_path).
Warning: Removed 1 rows containing missing values (geom_point).

Further, we just work on remainder time series, by removing trend and seasonality.
Removing trend and seasonality from data
We start with segment 1
Series: no_of_applicants_sum
Model: ARIMA(2,0,0)
Coefficients:
ar1 ar2
-0.1770 -0.2877
s.e. 0.0339 0.0339
sigma^2 estimated as 318.6: log likelihood=-3422.64
AIC=6851.28 AICc=6851.31 BIC=6865.32

For segment 2
Series: no_of_applicants_sum
Model: ARIMA(0,0,2)(0,0,2)[7]
Coefficients:
ma1 ma2 sma1 sma2
0.2541 -0.1037 0.0741 -0.2111
s.e. 0.0472 0.0539 0.0340 0.0320
sigma^2 estimated as 29586: log likelihood=-5343.5
AIC=10697.01 AICc=10697.08 BIC=10720.52

Removing trend and seasonality, aic and bic value reduces a lot, but when we observe it’s predictions we see that it has negative values, which doesn’t make sense. So, instead we should try INARIMA model here, to make sure that our output is positive only which can be done as future work.
HOLT WINTER’S EXPONENTIAL SMOOTHING
This method uses two parameters, one for the overall smoothing and the other for the trend smoothing equation. The method is also called double exponential smoothing or trend-enhanced exponential smoothing.For the given data we observe the data the component are additive hence we follow the additive method. This method is used since the forecast is for a short period and it doesn’t work well for long term predictions.

Here we observe the error rate increasing over time and after differentiation too the model captures only
library(patchwork)
e=autoplot(data_1.dif)
f=autoplot(ses.data_1.dif)
e

f


SARIMAX
Seasonal Auto-Regressive Integrated Moving Average with exogenous factors, or SARIMAX, is an extension of the ARIMA class of models. SARIMAX has the capability to handle exogenous variable like holidays. We can also get your own domain-specific features if you need to. In our case, we combined the original data with Indian holidays and built a SARIMAX model.
Initially the binary variables in Holiday column was converted to 1s and 0s from yes and no. This data is added as the exogenous variable into the ARIMAX model, making it SARIMAX.We use the method Maximum Likelihood Estimate to make the predictions. Fitting SARIMAX model with seasonal ARIMA order (2,2,0) for segment 1 and (4,2,0) for segment 2.
For Segment 1:
model_ts
Call:
arimax(x = (inf), order = c(0, 1, 1), seasonal = list(order = c(0, 1, 1), period = 12),
xreg = rinf, method = "ML")
Coefficients:
ma1 sma1 xreg
-0.9268 -1.0000 -14.5327
s.e. 0.0172 0.0163 6.5784
sigma^2 estimated as 604.9: log likelihood = -3261.34, aic = 6528.68
And a BIC score of :
BIC(model_ts)
[1] 6548.88
For Segment 2
model_ts1
Call:
arimax(x = (iinf), order = c(4, 2, 0), seasonal = list(order = c(4, 2, 0), period = 12),
xreg = rrinf, method = "ML")
Coefficients:
ar1 ar2 ar3 ar4 sar1 sar2 sar3 sar4 xreg
-0.8138 -0.4978 -0.4467 -0.3499 -1.4187 -1.2366 -0.8741 -0.4665 -19.4126
s.e. 0.0377 0.0449 0.0438 0.0380 0.0350 0.0571 0.0551 0.0340 52.4444
sigma^2 estimated as 195217: log likelihood = -5327.59, aic = 10673.17
BIC(model_ts1)
[1] 10720.78
Conclusion
From the above analysis we conclude that the model that better explains the above data is ARIMA.By changing the values (p,d,q) we can find the optimal value using the AIC and the BIC score which can help us in forecasting accurately.We learnt about dealing with trend and seasonality .The model can be improved further using residual components.
Team-9 members
Dona Sam -20BDA02
Pratibha KS - 20BDA15
Reba Susan- 20BDA37
Jayasree C-20BDA53
Abhijith - 20BDA60
Ananya Kumari- 20BDA68
LS0tDQp0aXRsZTogIlRpbWUgU2VyaWVzIEZvcmVjYXN0aW5nIg0Kb3V0cHV0OiBodG1sX25vdGVib29rDQotLS0NCmBgYHtyIGluY2x1ZGU9RkFMU0V9DQojaW5zdGFsbC5wYWNrYWdlcygoImRwbHlyIikpDQpsaWJyYXJ5KGRwbHlyKQ0KDQojaW5zdGFsbC5wYWNrYWdlcygoInRzaWJibGUiKSkNCmxpYnJhcnkodHNpYmJsZSkNCiNpbnN0YWxsLnBhY2thZ2VzKCJ4dHMiKQ0KbGlicmFyeSh4dHMpDQojaW5zdGFsbC5wYWNrYWdlcygiZ2dwbG90MiIpDQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KHJlc2hhcGUpDQpsaWJyYXJ5KHJlc2hhcGUyKQ0KbGlicmFyeSh0aWR5cikNCmxpYnJhcnkodGlkeXZlcnNlKQ0KbGlicmFyeShkYXRhLnRhYmxlKQ0KbGlicmFyeSh6b28pDQpsaWJyYXJ5KGJpemRheXMpDQpsaWJyYXJ5KGdnZWFzeSkNCmxpYnJhcnkoaGFycnlwb3R0ZXIpDQpsaWJyYXJ5KGJpemRheXMpDQpsaWJyYXJ5KHRpbWVEYXRlKQ0KbGlicmFyeShhc3RzYSkNCmxpYnJhcnkoZnBwMikNCg0KIyBWaXN1YWxpemF0aW9ucw0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeShwbG90bHkpDQpsaWJyYXJ5KE1BU1MpDQpsaWJyYXJ5KGRwbHlyKQ0KDQpsaWJyYXJ5KG1hZ3JpdHRyKQ0KbGlicmFyeShmb3JlY2FzdCkNCmxpYnJhcnkoZmVhc3RzKQ0KbGlicmFyeShHR2FsbHkpDQpsaWJyYXJ5KGZwcDIpDQpyZXF1aXJlKHN0YXRzKQ0KbGlicmFyeSh1cm9vdCkNCmluc3RhbGwucGFja2FnZXMoJ2ZhYmxlJykNCmxpYnJhcnkoZmFibGUpDQoNCmxpYnJhcnkobHVicmlkYXRlKQ0KbGlicmFyeSh6b28pDQpsaWJyYXJ5KG1hZ3JpdHRyKQ0KbGlicmFyeShmb3JlY2FzdCkNCiNpbnN0YWxsLnBhY2thZ2VzKCJmZWFzdHMiKQ0KbGlicmFyeShmZWFzdHMpDQojaW5zdGFsbC5wYWNrYWdlcygiR0dhbGx5IikNCmxpYnJhcnkoR0dhbGx5KQ0KbGlicmFyeShmcHAyKQ0KDQpgYGANCg0KIyBQcm9ibGVtIFN0YXRlbWVudCANCg0KTmVvIEJhbmsgb2YgSW5kaWEgKGEgZmljdGlvbmFsIGJhbmspIHJlY2VpdmVzIGEgbG90IG9mIHJlcXVlc3RzIGZvciBpdHMgdmFyaW91cyBmaW5hbmNlIG9mZmVyaW5ncyB0aGF0IGluY2x1ZGUgaG91c2luZyBsb2FucywgdHdvLXdoZWVsZXIgbG9hbnMsIHJlYWwgZXN0YXRlIGZpbmFuY2luZywgYW5kIG1pY3JvbG9hbnMuIFRoZSBudW1iZXIgb2YgYXBwbGljYXRpb25zIHJlY2VpdmVkIGlzIHNvbWV0aGluZyB0aGF0IHZhcmllcyBhIGxvdCB3aXRoIHRoZSBzZWFzb24uIEdvaW5nIHRocm91Z2ggdGhlc2UgYXBwbGljYXRpb25zIGlzIGEgbWFudWFsIGFuZCB0ZWRpb3VzIHByb2Nlc3MuDQoNCkFjY3VyYXRlbHkgZm9yZWNhc3RpbmcgdGhlIG51bWJlciBvZiBjYXNlcyByZWNlaXZlZCBjYW4gaGVscCB3aXRoIHJlc291cmNlIGFuZCBtYW5wb3dlciBtYW5hZ2VtZW50IHJlc3VsdGluZyBpbiBxdWljayByZXNwb25zZSBvbiBhcHBsaWNhdGlvbnMgYW5kIG1vcmUgZWZmaWNpZW50IHByb2Nlc3NpbmcuDQpZb3UgaGF2ZSBiZWVuIGFwcG9pbnRlZCB3aXRoIHRoZSB0YXNrIG9mIGZvcmVjYXN0aW5nIGRhaWx5IGNhc2VzIGZvciB0aGUgbmV4dCAxIG1vbnRoIGZvciAyIGRpZmZlcmVudCBidXNpbmVzcyBzZWdtZW50cyBhZ2dyZWdhdGVkIGF0IHRoZSBjb3VudHJ5IGxldmVsIGtlZXBpbmcgaW4gY29uc2lkZXJhdGlvbiB0aGUgZm9sbG93aW5nIG1ham9yIEluZGlhbiBmZXN0aXZhbHMgKGluY2x1c2l2ZSBidXQgbm90IGV4aGF1c3RpdmUgbGlzdCk6IERpd2FsaSwgRHVzc2VocmEsIEdhbmVzaCBDaGF0dXJ0aGksIE5hdnJhdHJpLCBIb2xpLCBldGMuDQoNCiMgRGF0YQ0KDQpUaGUgZGF0YXNldCBpcyBkaXZpZGVkIGludG8gMiBjb21wb25lbnRzLCBuYW1lbHkgdHJhaW4gZGF0YSBhbmQgdGVzdCBkYXRhLiBUaGUgdHJhaW5pbmcgZGF0YSBjb25zaXN0cyBvZiBkZXBlbmRlbnQgdmFyaWFibGVzIHN1Y2ggYXMgZGF0ZSBvZiBhcHBsaWNhdGlvbiAoYXBwbGljYXRpb25fZGF0ZSksIGJ1c2luZXNzIHNlZ21lbnQgKHNlZ21lbnQgMSBvciAyKSwgYW5vbnltaXplZCBpZCBmb3IgYSBicmFuY2ggYXQgd2hpY2ggYXBwbGljYXRpb24gd2FzIHJlY2VpdmVkIChicmFuY2hfaWQpLCBTdGF0ZSBpbiB3aGljaCBhcHBsaWNhdGlvbiB3YXMgcmVjZWl2ZWQgKHN0YXRlKSwgem9uZSBvZiBzdGF0ZSBpbiB3aGljaCBhcHBsaWNhdGlvbiB3YXMgcmVjZWl2ZWQgKHpvbmUpLiBUaGUgdGFyZ2V0IHZhcmlhYmxlIGhlcmUgaXMgdGhlIG51bWJlciBvZiBjYXNlcy9hcHBsaWNhdGlvbnMgcmVjZWl2ZWQgKG5vX29mX2FwcGxpY2FudHMpLg0KDQpUaGUgdGVzdCBkYXRhIGNvbnNpc3RzIG9mIGEgdW5pcXVlIGlkIGZvciBlYWNoIHNhbXBsZSBpbiB0aGUgdGVzdCBzZXQgKGlkKSwgRGF0ZSBvZiBhcHBsaWNhdGlvbiAoYXBwbGljYXRpb25fZGF0ZSksIGJ1c2luZXNzIHNlZ21lbnQgKHNlZ21lbnQpLiANCg0KU2FtcGxlIHN1Ym1pc3Npb24gY29uc2lzdHMgb2YgaWQgd2l0aCB0aGUgbnVtYmVyIG9mIGFwcGxpY2FudHMgZm9yZWNhc3RlZCBmb3IgbmV4dCBtb250aCBmb3IgYnVzaW5lc3Mgc2VnbWVudHMgMSBhbmQgMi4NCg0KDQojIEV2YWx1YXRpb24gTWV0cmljcw0KDQpFdmFsdWF0aW9uIGZvciB0aGUgZ2l2ZW4gY2FzZSBpcyBNQVBFIC0gTWVhbiBBYnNvbHV0ZSBQZXJjZW50YWdlIEVycm9yDQoNCg0KIyBEYXRhIFByZXByb2Nlc3NpbmcNCg0KSW4gdGhlIGdpdmVuIGRhdGEgYXMgYSBwYXJ0IG9mIHByZS1wcm9jZXNzaW5nIHdlIGRpdmlkZSB0aGUgZGF0YSBiYXNlZCBvbiB0aGUgYnVzaW5lc3Mgc2VnbWVudHMgdG8gYW5hbHl6ZSB0aGVtIGluZGl2aWR1YWxseSBmb3IgdGhlIG1pc3NpbmcgdmFsdWVzIHdlIHVzZSBJbnRlcnBvbGF0aW9uIHRvIGZpbGwgaW4gdGhlIG1pc3NpbmcgdmFsdWVzLldlIGNvbWJpbmVkIHRoZSBkYXRhc2V0IHdpdGggSG9saWRheSBkYXRhc2V0IGRvd25sb2FkZWQgZnJvbSBLYWdnbGUgdGhyb3VnaCBsZWZ0IGpvaW4uIFRoaXMgZmluYWwgZGF0YXNldCBpcyB1c2VkIGZvciBmdXJ0aGVyIGFuYWx5c2lzLiBUaGUgSG9saWRheSBkYXRhc2V0IGNvbnNpc3RzIG9mIGFsbCB0aGUgSW5kaWFuIGhvbGlkYXlzIGZvciBhIHBlcmlvZCBvZiAyMDE3IHRvIDIwMTkuVGhlIGRhdGEgdHlwZSBvZiB0aGUgQXBwbGljYXRpb24gZGF0ZSBpcyBhbHNvIG1vZGlmaWVkIHRvICdkYXRldGltZScgdHlwZSBhbmQgdGhlIGRhdGFmcmFtZXMgZm9yIGluZG92aWR1YWwgc2VnbWVudHMgYXJlIGNvbnZlcnRlZCB0byAndHNpYmJsZScgb2JqZWN0IGZvciB0aW1lIHNlcmllcyBhbmFseXNpcy4NCg0KDQoNCiMgRXhwbG9yYXRvcnkgRGF0YSBBbmFseXNpcw0KDQpPdmVyYWxsIHdlIG9ic2VydmUgdGhhdCB0aGUgZGF0YSBmcm9tIHRoZSBwZXJpb2QgMjAxNyB0byAyMDE5IHRlbmRzIHRvIGJlIHNlYXNvbmFsIHdpdGggcGVha3MgZHVyaW5nIHRoZSBtaWQtbW9udGhzLlRoZSBudW1iZXIgb2YgYXBwbGljYW50cyBpbiAyMDE3IGFuZCBlYXJseSAyMDE5IHRlbmQgdG8gYmUgY29tcGFyYXRpdmVseSBsb3cgYW5kIGluY29uc2lzdGVudCB3aXRoIHRoZSB0cmVuZCBvYnNlcnZlZCBkdXJpbmcgdGhlIGxhdGUtMjAxNyBhbmQgdGhlIHllYXIgMjAxOCwgdGhpcyBtYXkgYmUgZHVlIHRvIHRoZSByZWNvdmVyeSBmcm9tIHRoZSBkZW1vbmV0aXphdGlvbiBpbiBOb3ZlbWJlci0yMDE2LlRoaXMgIGluY29uc2lzdGVudCBkYXRhIG1heSBsZWFkIHRvIG5vaXNlIHdoaWxlIGZvcmVjYXN0aW5nLg0KT24gZGl2aWRpbmcgYmFzZWQgb24gc2VnbWVudHMgDQpgYGB7ciBpbmNsdWRlPUZBTFNFfQ0KI1JlYWRpbmcgdGhlIGZpbGVzIGZvciB0ZXN0IGFuZCB0cmFpbg0KdHJhaW4gPSByZWFkLmNzdigidHJhaW4uY3N2IikNCnRlc3QgPSByZWFkLmNzdigidGVzdC5jc3YiKQ0KDQpob2xpZGF5PXJlYWQuY3N2KCJpbmRpYW5faG9saWRheXMuY3N2IikNCmNvbG5hbWVzKGhvbGlkYXkpPC1jKCJhcHBsaWNhdGlvbl9kYXRlIiwiSG9saWRheSIpDQp0cmFpbjwtIHRyYWluICU+JSBsZWZ0X2pvaW4oaG9saWRheSxieT0iYXBwbGljYXRpb25fZGF0ZSIpDQp0cmFpbiRhcHBsaWNhdGlvbl9kYXRlPWFzLkRhdGUodHJhaW4kYXBwbGljYXRpb25fZGF0ZSwgIiVkLSVtLSVZIikNCnN1bW1hcnkodHJhaW4pDQpgYGANCmBgYHtyIGluY2x1ZGU9IEZBTFNFfQ0KdHJhaW4NCmBgYA0KDQpgYGB7ciBpbmNsdWRlPSBGQUxTRX0NCnRyYWluJEhvbGlkYXkgPC0gdHJhaW4kSG9saWRheSAlPiUgcmVwbGFjZV9uYSgnMCcpDQoNCnRyYWluDQpgYGANCg0KDQpgYGB7ciBpbmNsdWRlPUZBTFNFfQ0KI0NvbnZlcnRpbmcgYXBwbGljYXRpb24gZGF0ZSBpbnRvIGRhdGUgZm9ybWF0Lg0KdHJhaW4kYXBwbGljYXRpb25fZGF0ZTwtYXMuRGF0ZSh0cmFpbiRhcHBsaWNhdGlvbl9kYXRlLGZvcm1hdCA9ICIlZC0lbS0lWSIpDQp0cmFpbiRzZWdtZW50PC1hcy5jaGFyYWN0ZXIodHJhaW4kc2VnbWVudCkNCiMgIyBjb252ZXJ0aW5nIGhvbGlkYXkgZGF0YSBpbnRvIGRhdGUgZm9ybWF0DQojIHRyYWluX2hvbGlkYXlzJGFwcGxpY2F0aW9uX2RhdGU8LWFzLkRhdGUodHJhaW4kYXBwbGljYXRpb25fZGF0ZSxmb3JtYXQgPSAiJWQtJW0tJVkiKQ0KIyB0cmFpbl9ob2xpZGF5cyRzZWdtZW50PC1hcy5jaGFyYWN0ZXIodHJhaW4kc2VnbWVudCkNCnN0cih0cmFpbikNCmBgYA0KYGBge3IgaW5jbHVkZT1GQUxTRX0NCmNvbG5hbWVzKHRyYWluKQ0KYGBgDQpgYGB7ciBlY2hvPSBGQUxTRSwgaW5jbHVkZT1GQUxTRX0NCiNSZXBsYWNpbmcgdmFsdWVzIGZvciBjZXJ0YWluIGNvbHVtbnMgDQojIHRyYWluJHpvbmUgJT4lIHJlcGxhY2VfbmEoIk5vdCBTcGVjaWZpZWQiKQ0KIyB0cmFpbiRzdGF0ZSAlPiUgcmVwbGFjZV9uYSgiTm90IFNwZWNpZmllZCIpDQojIHRyYWluJGJyYW5jaF9pZCAlPiUgcmVwbGFjZV9uYSgiTm90IFNwZWNpZmllZCIpDQpgYGANCg0KDQpgYGB7ciBpbmNsdWRlPUZBTFNFfQ0KI0FkZGluZyBhZGRpdGlvbmFsIGNvbHVtbnMgb2YgZGF0ZSwgbW9udGggYW5kIHllYXIgDQp0cmFpbiREYXk8LWZvcm1hdCh0cmFpbiRhcHBsaWNhdGlvbl9kYXRlLCIlZCIpDQp0cmFpbiRNb250aDwtZm9ybWF0KHRyYWluJGFwcGxpY2F0aW9uX2RhdGUsIiVtIikNCnRyYWluJFllYXI8LWZvcm1hdCh0cmFpbiRhcHBsaWNhdGlvbl9kYXRlLCIlWSIpDQp0cmFpbg0KDQoNCg0KIyBjb2xTdW1zKHNhcHBseSh0cmFpbiwgaXMubmEpKQ0KIyB0cmFpbiA8LSBuYS5vbWl0KHRyYWluKQ0KIyB0cmFpbiAlPiUgZGlzdGluY3QoKQ0KIyANCiMgI0NvbnZlcnRpbmcgdG8gdHNpYmJsZQ0KIyB0cmFpbiA8LSB0cmFpbiU+JQ0KIyAgIG11dGF0ZShRdWFydGVyID0geWVhcnF1YXJ0ZXIoRGF0ZSkpICU+JQ0KIyAgIHNlbGVjdCgtRGF0ZSkgJT4lDQojICAgYXNfdHNpYmJsZShrZXkgPSBjKHNlZ21lbnQsYnJhbmNoX2lkLG5vX29mX2FwcGxpY2FudHMpLA0KIyAgICAgICAgICAgICAgaW5kZXggPSBRdWFydGVyKQ0KIyAjQ29udmVydGluZyB0byB0aW1lIHNlcmllcyBvYmplY3QNCiMgI3RyYWluX3RzIDwtIHh0cyh0cmFpbiRub19vZl9hcHBsaWNhbnRzLHRyYWluJGFwcGxpY2F0aW9uX2RhdGUpDQojICN0cmFpbl90cw0KIyAjTnVsbCB2YWx1ZXMgaWpuIGVhY2ggY29sdW1uDQoNCg0KDQpgYGANCmBgYHtyIGluY2x1ZGU9RkFMU0V9DQojUmVtb3Zpbmcgcm93cyB3aXRoIGFueSBtaXNzaW5nIHZhbHVlcyANCiN0cmFpbiA8LSB0cmFpbltjb21wbGV0ZS5jYXNlcyh0cmFpbiksIF0NCnRyYWluDQpgYGANCmBgYHtyIGluY2x1ZGU9RkFMU0V9DQpkaW0odHJhaW4pDQpgYGANCmBgYHtyIGluY2x1ZGU9RkFMU0V9DQojU3BsaXR0aW5nIHRoZSBkYXRhZnJhbWUgYmFzZWQgb24gc2VnbWVudA0KU2VnbWVudDEgPC0gdHJhaW4lPiUgZmlsdGVyKHNlZ21lbnQ9PSAnMScpDQpWaWV3KFNlZ21lbnQxKQ0KU2VnbWVudDIgPC0gdHJhaW4lPiUgZmlsdGVyKHNlZ21lbnQ9PSAnMicpDQpWaWV3KFNlZ21lbnQyKQ0KYGBgDQpgYGB7ciBpbmNsdWRlPUZBTFNFfQ0KI1JlbW92aW5nIHJvd3Mgd2l0aCBhbnkgbWlzc2luZyB2YWx1ZXMgDQp0cmFpbl90cyA8LSB0cmFpbltjb21wbGV0ZS5jYXNlcyh0cmFpbiksIF0NCmBgYA0KDQpgYGB7ciBpbmNsdWRlPUZBTFNFfQ0KI0NoYW5naW5nIHRoZSBkYXRhZnJhbWUgdG8gcyB0aW1lIHNlcmllcyBvYmplY3QNCnRyYWluX3RzPC0gdHJhaW5fdHMgJT4lDQogIG11dGF0ZShRdWFydGVyID0geWVhcnF1YXJ0ZXIoYXBwbGljYXRpb25fZGF0ZSkpICU+JQ0KICBhc190c2liYmxlKGtleSA9IGMoc2VnbWVudCxicmFuY2hfaWQsc3RhdGUsem9uZSxub19vZl9hcHBsaWNhbnRzLERheSxNb250aCxZZWFyLEhvbGlkYXkpLA0KICAgICAgICAgICAgIGluZGV4ID0gUXVhcnRlcikNCg0KDQpgYGANCmBgYHtyIGluY2x1ZGU9RkFMU0V9DQojIHRyYWluX3RzIDwtIHh0cyh0cmFpbiRub19vZl9hcHBsaWNhbnRzLHRyYWluJERhdGUpDQpjbGFzcyh0cmFpbl90cykNCmRpbSh0cmFpbl90cykNCmBgYA0KDQoNCmBgYHtyIHdhcm5pbmc9RkFMU0UsaW5jbHVkZT1GQUxTRX0NCmZpZyA8LSBwbG90X2x5KHRyYWluLCB0eXBlID0gJ3NjYXR0ZXInLCBtb2RlID0gJ2xpbmVzJyklPiUNCiAgYWRkX3RyYWNlKHggPSB+YXBwbGljYXRpb25fZGF0ZSwgeSA9IH5ub19vZl9hcHBsaWNhbnRzKSU+JQ0KICBsYXlvdXQoc2hvd2xlZ2VuZCA9IEYsIHdpZHRoPTYwMCkNCmZpZyA8LSBmaWcgJT4lDQogIGxheW91dCgNCiAgICAgICAgIHhheGlzID0gbGlzdCh6ZXJvbGluZWNvbG9yID0gJyNmZmZmJywNCiAgICAgICAgICAgICAgICAgICAgICB6ZXJvbGluZXdpZHRoID0gMiwNCiAgICAgICAgICAgICAgICAgICAgICBncmlkY29sb3IgPSAnZmZmZicpLA0KICAgICAgICAgeWF4aXMgPSBsaXN0KHplcm9saW5lY29sb3IgPSAnI2ZmZmYnLA0KICAgICAgICAgICAgICAgICAgICAgIHplcm9saW5ld2lkdGggPSAyLA0KICAgICAgICAgICAgICAgICAgICAgIGdyaWRjb2xvciA9ICdmZmZmJyksDQogICAgICAgICBwbG90X2JnY29sb3I9JyNlNWVjZjYnLCB3aWR0aCA9IDgwMCkNCmBgYA0KDQoNCmBgYHtyIHdhcm5pbmc9RkFMU0UsIGluY2x1ZGU9RkFMU0V9DQojZmlnDQpgYGANCmBgYHtyIGluY2x1ZGU9RkFMU0V9DQojIGZpZyA8LSBwbG90X2x5KCklPiUNCiMgICBhZGRfdHJhY2UoZGF0YSA9IHRyYWluLCB0eXBlID0gJ3NjYXR0ZXInLCBtb2RlID0gJ2xpbmVzJywgZmlsbCA9ICd0b3plcm95JywgeCA9IH5hcHBsaWNhdGlvbl9kYXRlLCB5ID0gfm5vX29mX2FwcGxpY2FudHMsIG5hbWUgPSAnTm8ub2YgYXBwbGljYW50cycpJT4lDQojICAgbGF5b3V0KHNob3dsZWdlbmQgPSBGLA0KIyAgICAgICAgICAgemVyb2xpbmVjb2xvciA9ICcjZmZmZicsDQojICAgICAgICAgICAgICAgICAgICAgICB6ZXJvbGluZXdpZHRoID0gMiwNCiMgICAgICAgICAgICAgICAgICAgICAgIGdyaWRjb2xvciA9ICdmZmZmJyksDQojICAgICAgICAgIHhheGlzID0gbGlzdCh6ZXJvbGluZWNvbG9yID0gJyNmZmZmJywNCiMgICAgICAgICAgICAgICAgICAgICAgIHplcm9saW5ld2lkdGggPSAyLA0KIyAgICAgICAgICAgICAgICAgICAgICAgZ3JpZGNvbG9yID0gJ2ZmZmYnKSwNCiMgICAgICAgICAgcGxvdF9iZ2NvbG9yPScjZTVlY2Y2JykNCiMgb3B0aW9ucyh3YXJuID0gLTEpDQojIGZpZyA8LSBmaWcgJT4lDQojICAgbGF5b3V0KA0KIyAgICAgICAgICB4YXhpcyA9IGxpc3QoemVyb2xpbmVjb2xvciA9ICcjZmZmZicsDQojICAgICAgICAgICAgICAgICAgICAgICB6ZXJvbGluZXdpZHRoID0gMiwNCiMgICAgICAgICAgICAgICAgICAgICAgIGdyaWRjb2xvciA9ICdmZmZmJyksDQojICAgICAgICAgIHlheGlzID0gbGlzdCh6ZXJvbGluZWNvbG9yID0gJyNmZmZmJywNCiMgICAgICAgICAgICAgICAgICAgICAgIHplcm9saW5ld2lkdGggPSAyLA0KIyAgICAgICAgICAgICAgICAgICAgICAgZ3JpZGNvbG9yID0gJ2ZmZmYnKSwNCiMgICAgICAgICAgcGxvdF9iZ2NvbG9yPScjZTVlY2Y2Jywgd2lkdGggPSAxMDAwKQ0KIyANCiMgDQojIGZpZw0KYGBgDQoNCmBgYHtyIGluY2x1ZGU9RkFMU0V9DQojQ291bnQgYmFzZWQgb24gem9uZSwgc3RhdGUsc2VnbWVudCBhbmQgZGF0ZQ0KDQp6b25lX2NvdW50PC0gY291bnQodHJhaW4sem9uZSkNCiMgVmlldyh6b25lX2NvdW50KQ0KDQp6b25lX2NvdW50X3Bsb3QgPC0gcGxvdF9seSh6b25lX2NvdW50LCB4PX56b25lLCB5ID0gfm4sIHR5cGUgPSAnYmFyJyxuYW1lID0gfnpvbmUsDQp0ZXh0ID0gfm4sIHRleHRwb3NpdGlvbiA9ICdhdXRvJywgd2lkdGggPSAxLjUpDQp6b25lX2NvdW50X3Bsb3QgPC0gem9uZV9jb3VudF9wbG90ICAlPiUgbGF5b3V0KHRpdGxlID0gIlpPTkUgQ09VTlQiLA0KeGF4aXMgPSBsaXN0KHRpdGxlID0gIlpPTkUiKSwNCnlheGlzID0gbGlzdCh0aXRsZSA9ICJOTy5PRiBBUFBMSUNBTlRTIikpDQoNCg0KI1N0YXRlDQoNCnN0YXRlX2NvdW50PC0gY291bnQodHJhaW4sc3RhdGUpDQojVmlldyhzdGF0ZV9jb3VudCkNCg0Kc3RhdGVfY291bnRfcGxvdCA8LSBwbG90X2x5KHN0YXRlX2NvdW50LCB4PX5zdGF0ZSwgeSA9IH5uLCB0eXBlID0gJ2JhcicsbmFtZSA9IH5zdGF0ZSwNCnRleHQgPSB+biwgdGV4dHBvc2l0aW9uID0gJ2F1dG8nLCB3aWR0aCA9IDEpDQpzdGF0ZV9jb3VudF9wbG90IDwtIHN0YXRlX2NvdW50X3Bsb3QgICU+JSBsYXlvdXQodGl0bGUgPSAiU1RBVEUgQ09VTlQiLA0KeGF4aXMgPSBsaXN0KHRpdGxlID0gIlNUQVRFIix0aWNrYW5nbGUgPSA5MCksDQp5YXhpcyA9IGxpc3QodGl0bGUgPSAiTk8uT0YgQVBQTElDQU5UUyIpKQ0KDQojc3RhdGVfY291bnRfcGxvdCANCiNTZWdtZW50DQoNCnNlZ21lbnRfY291bnQ8LSBjb3VudCh0cmFpbixzZWdtZW50KQ0KI1ZpZXcoc2VnbWVudF9jb3VudCkNCg0Kc2VnbWVudF9jb3VudF9wbG90IDwtcGxvdF9seShzZWdtZW50X2NvdW50LCBsYWJlbHMgPSB+c2VnbWVudCwgdmFsdWVzID0gfm4sIHR5cGUgPSAncGllJykNCnNlZ21lbnRfY291bnRfcGxvdCA8LSBzZWdtZW50X2NvdW50X3Bsb3QgJT4lIGxheW91dCh0aXRsZSA9ICdPVkVSQUxMIFNFR01FTlQgRElTVFJJQlVUSU9OJywNCnhheGlzID0gbGlzdChzaG93Z3JpZCA9IEZBTFNFLCB6ZXJvbGluZSA9IEZBTFNFLCBzaG93dGlja2xhYmVscyA9IEZBTFNFKSwNCnlheGlzID0gbGlzdChzaG93Z3JpZCA9IEZBTFNFLCB6ZXJvbGluZSA9IEZBTFNFLCBzaG93dGlja2xhYmVscyA9IEZBTFNFKSkNCmBgYA0KDQpXZSBvYnNlcnZlIHRoYXQgbWFqb3JpdHkgb2YgdGhlIGFwcGxpY2F0aW9ucyBiZWxvbmcgdG8gU2VnbWVudCAxIGFuZCB0aGUgem9uZSB0byByZWNlaXZlIGhpZ2hlc3QgbnVtYmVyIG9mIGFwcGxpY2F0aW9ucyBpcyB0aGUgRWFzdCB6b25lLiBJdCBpcyBvYnNlcnZlZCB0aGF0IHRoZSBzdGF0ZSBvZiBNYWhhcmFzaHRyYSBoYXMgaGlnaGVzdCBudW1iZXIgb2YgYXBwbGljYXRpb24gYWNyb3NzIGlzIGJyYW5jaGVzIGZyb20gMjAxNy0yMDE5Lg0KYGBge3J9DQoNCg0Kc2VnbWVudF9jb3VudF9wbG90IA0Kem9uZV9jb3VudF9wbG90DQpgYGANCmBgYHtyIHdhcm5pbmc9RkFMU0UsaW5jbHVkZT1GQUxTRX0NCmdncGxvdCh0cmFpbiwgYWVzKHggPXRyYWluJGFwcGxpY2F0aW9uX2RhdGUsIHkgPSB0cmFpbiRub19vZl9hcHBsaWNhbnRzLCBjb2xvciA9IH5zZWdtZW50KSkgKw0KICBnZW9tX2FyZWEoY29sb3VyID0gImJsYWNrIiwgc2l6ZSA9IC4yLCBhbHBoYSA9IC40KSArDQogIHNjYWxlX2ZpbGxfYnJld2VyKHBhbGV0dGUgPSAiQmx1ZXMiKQ0KYGBgDQoNCmBgYHtyIHdhcm5pbmc9RkFMU0UsaW5jbHVkZT1GQUxTRX0NCmZpZyA8LSBwbG90X2x5KHRyYWluLHggPXRyYWluJGFwcGxpY2F0aW9uX2RhdGUsIHkgPSB0cmFpbiRub19vZl9hcHBsaWNhbnRzLCBjb2xvciA9IH5zZWdtZW50KSANCmZpZyA8LSBmaWcgJT4lIGFkZF9saW5lcygpDQoNCmZpZw0KYGBgDQpgYGB7ciBpbmNsdWRlPUZBTFNFfQ0KdHJhaW4NCmBgYA0KDQpgYGB7ciB3YXJuaW5nID0gRkFMU0UsIG1lc3NhZ2U9IEZBTFNFLCBlY2hvPUZBTFNFLGluY2x1ZGU9RkFMU0V9DQojR3JvdXAgYnkgZGF0YSBvbiB0aGUgYmFzaXMgb2YgYXBwbGljYXRpb25fZGF0ZSxzZWdtZW50IGFuZCBzdW0gbm9fb2ZfYXBwbGljYW50cy4NCg0KZGF0YV9ncnA8LXRyYWluICU+JSBncm91cF9ieShhcHBsaWNhdGlvbl9kYXRlLHNlZ21lbnQsSG9saWRheSkgJT4lIA0KICAgICAgIHN1bW1hcmlzZShub19vZl9hcHBsaWNhbnRzX3N1bSAgPSBtZWFuKG5vX29mX2FwcGxpY2FudHMpKQ0KVmlldyhkYXRhX2dycCkNCmBgYA0KYGBge3IgZWNobz1GQUxTRSxpbmNsdWRlPUZBTFNFfQ0KIyMgQ3JlYXRlIHR3byBkYXRhZnJhbWVzDQoNCiNGaWx0ZXIgZGF0YSBmcmFtZXMgYmFzZWQgb24gc2VnbWVudCwgdGhlbiBjb252ZXJ0IHRoZW0gaW50byB0c2liYmxlIGZvciBzZWdtZW50IDENCmRhdGFfMTwtZGF0YV9ncnAgJT4lIGZpbHRlcihzZWdtZW50ICVpbiUgYygxKSkNCmRhdGFfMTwtZGF0YV8xICU+JW11dGF0ZShhcHBsaWNhdGlvbl9kYXRlID0gYXMuRGF0ZShhcHBsaWNhdGlvbl9kYXRlKSkgJT4lDQogIGFzX3RzaWJibGUoaW5kZXggPSBhcHBsaWNhdGlvbl9kYXRlKQ0KYGBgDQoNCg0KYGBge3IgaW5jbHVkZT1GQUxTRX0NCiNGb3Igc2VnbWVudCAxLCBmaWxsIGdhcHMgZm9yIG1pc3NpbmcgdmFsdWVzDQoNCg0KDQpoaDwtIGRhdGEuZnJhbWUoYXBwbGljYXRpb25fZGF0ZT1zZXEobWluKGRhdGFfMSRhcHBsaWNhdGlvbl9kYXRlKSwgbWF4KGRhdGFfMSRhcHBsaWNhdGlvbl9kYXRlKSwgYnk9ImRheXMiKSkNCmRhdGFfMSA8LSBtZXJnZShkYXRhXzEsaGgsYnkueD0nYXBwbGljYXRpb25fZGF0ZScsYnkueT0nYXBwbGljYXRpb25fZGF0ZScsYWxsLng9VCxhbGwueT1UKQ0KZGF0YV8xJHNlZ21lbnRbaXMubmEoZGF0YV8xJHNlZ21lbnQpXSA8LSAxDQpkYXRhXzEkc2VnbWVudCA8LSBOVUxMDQpoZWFkKGRhdGFfMSkNCmRhdGFfMTwtZGF0YV8xICU+JW11dGF0ZShhcHBsaWNhdGlvbl9kYXRlID0gYXMuRGF0ZShhcHBsaWNhdGlvbl9kYXRlKSkgJT4lDQogIGFzX3RzaWJibGUoaW5kZXggPSBhcHBsaWNhdGlvbl9kYXRlKQ0KaXNfdHNpYmJsZShkYXRhXzIpDQpgYGANCg0KDQpgYGB7ciBlY2hvPUZBTFNFLCBpbmNsdWRlPUZBTFNFfQ0KI0ZvciBzZWdtZW50IDEsIGludGVycG9sYXRpb24gZm9yIG1pc3NpbmcgdmFsdWVzIG9mIG51bWJlciBvZiBhcHBsaWNhbnRzDQoNCnggPC0gem9vKGRhdGFfMSRub19vZl9hcHBsaWNhbnRzX3N1bSxkYXRhXzEkYXBwbGljYXRpb25fZGF0ZSkNCnggPC0gYXMudHMocm91bmQoeCkpDQpkYXRhXzEkbm9fb2ZfYXBwbGljYW50c19zdW0gPC0gbmEuaW50ZXJwKHJvdW5kKHgpKQ0KaXNfdHNpYmJsZShkYXRhXzEpDQoNCg0KYGBgDQpgYGB7ciBpbmNsdWRlPUZBTFNFfQ0KI0ZpbHRlciBkYXRhZnJhbWVzIGJhc2VkIG9uIHNlZ21lbnQsIHRoZW4gY29udmVydCB0aGVtIGludG8gdHNpYmJsZSBmb3Igc2VnbWVudCAyDQpkYXRhXzI8LWRhdGFfZ3JwICU+JSBmaWx0ZXIoc2VnbWVudCAlaW4lIGMoMikpDQpkYXRhXzI8LWRhdGFfMiAlPiVtdXRhdGUoYXBwbGljYXRpb25fZGF0ZSA9IGFzLkRhdGUoYXBwbGljYXRpb25fZGF0ZSkpICU+JQ0KICBhc190c2liYmxlKGluZGV4ID0gYXBwbGljYXRpb25fZGF0ZSkNCg0KYGBgDQoNCg0KYGBge3IgaW5jbHVkZT1GQUxTRX0NCiNGb3Igc2VnbWVudCAyLCBmaWxsIGdhcHMgZm9yIG1pc3NpbmcgdmFsdWVzDQoNCg0KaGg8LSBkYXRhLmZyYW1lKGFwcGxpY2F0aW9uX2RhdGU9c2VxKG1pbihkYXRhXzIkYXBwbGljYXRpb25fZGF0ZSksIG1heChkYXRhXzIkYXBwbGljYXRpb25fZGF0ZSksIGJ5PSJkYXlzIikpDQpkYXRhXzIgPC0gbWVyZ2UoZGF0YV8yLGhoLGJ5Lng9J2FwcGxpY2F0aW9uX2RhdGUnLGJ5Lnk9J2FwcGxpY2F0aW9uX2RhdGUnLGFsbC54PVQsYWxsLnk9VCkNCmRhdGFfMiRzZWdtZW50W2lzLm5hKGRhdGFfMiRzZWdtZW50KV0gPC0gMQ0KZGF0YV8yJHNlZ21lbnQgPC0gTlVMTA0KaGVhZChkYXRhXzIpDQpkYXRhXzI8LWRhdGFfMiAlPiVtdXRhdGUoYXBwbGljYXRpb25fZGF0ZSA9IGFzLkRhdGUoYXBwbGljYXRpb25fZGF0ZSkpICU+JQ0KICBhc190c2liYmxlKGluZGV4ID0gYXBwbGljYXRpb25fZGF0ZSkNCmlzX3RzaWJibGUoZGF0YV8yKQ0KYGBgDQoNCg0KDQpgYGB7ciBpbmNsdWRlPUZBTFNFfQ0KI0ZvciBzZWdtZW50IDIsIGludGVycG9sYXRpb24gZm9yIG1pc3NpbmcgdmFsdWVzIG9mIG51bWJlciBvZiBhcHBsaWNhbnRzDQoNCnggPC0gem9vKGRhdGFfMiRub19vZl9hcHBsaWNhbnRzX3N1bSxkYXRhXzIkYXBwbGljYXRpb25fZGF0ZSkNCnggPC0gYXMudHMocm91bmQoeCkpDQpkYXRhXzIkbm9fb2ZfYXBwbGljYW50c19zdW0gPC0gbmEuaW50ZXJwKHJvdW5kKHgpKQ0KaXNfdHNpYmJsZShkYXRhXzIpDQoNCmBgYA0KDQoNCmBgYHtyIGluY2x1ZGU9IEZBTFNFfQ0Kc3VtKGlzLm5hKGRhdGFfMSkpDQpzdW0oaXMubmEoZGF0YV8yKSkNCmBgYA0KYGBge3J9DQoNCmRhdGFfZ3JwcDwtdHJhaW4gJT4lIGdyb3VwX2J5KGFwcGxpY2F0aW9uX2RhdGUsc2VnbWVudCkgJT4lIA0KICAgICAgIHN1bW1hcmlzZShub19vZl9hcHBsaWNhbnRzX3N1bSAgPSBtZWFuKG5vX29mX2FwcGxpY2FudHMpKQ0KVmlldyhkYXRhX2dycHApDQoNCiNGaWx0ZXIgZGF0YSBmcmFtZXMgYmFzZWQgb24gc2VnbWVudCwgdGhlbiBjb252ZXJ0IHRoZW0gaW50byB0c2liYmxlIGZvciBzZWdtZW50IDENCmRhdGFfMTE8LWRhdGFfZ3JwcCAlPiUgZmlsdGVyKHNlZ21lbnQgJWluJSBjKDEpKQ0KZGF0YV8xMTwtZGF0YV8xMSAlPiVtdXRhdGUoYXBwbGljYXRpb25fZGF0ZSA9IGFzLkRhdGUoYXBwbGljYXRpb25fZGF0ZSkpICU+JQ0KICBhc190c2liYmxlKGluZGV4ID0gYXBwbGljYXRpb25fZGF0ZSkNCmBgYA0KDQoNCmBgYHtyIGluY2x1ZGU9RkFMU0V9DQojRm9yIHNlZ21lbnQgMSwgZmlsbCBnYXBzIGZvciBtaXNzaW5nIHZhbHVlcw0KDQoNCg0KaGg8LSBkYXRhLmZyYW1lKGFwcGxpY2F0aW9uX2RhdGU9c2VxKG1pbihkYXRhXzExJGFwcGxpY2F0aW9uX2RhdGUpLCBtYXgoZGF0YV8xMSRhcHBsaWNhdGlvbl9kYXRlKSwgYnk9ImRheXMiKSkNCmRhdGFfMTEgPC0gbWVyZ2UoZGF0YV8xMSxoaCxieS54PSdhcHBsaWNhdGlvbl9kYXRlJyxieS55PSdhcHBsaWNhdGlvbl9kYXRlJyxhbGwueD1ULGFsbC55PVQpDQpkYXRhXzExJHNlZ21lbnRbaXMubmEoZGF0YV8xMSRzZWdtZW50KV0gPC0gMQ0KZGF0YV8xMSRzZWdtZW50IDwtIE5VTEwNCmhlYWQoZGF0YV8xMSkNCmRhdGFfMTE8LWRhdGFfMTEgJT4lbXV0YXRlKGFwcGxpY2F0aW9uX2RhdGUgPSBhcy5EYXRlKGFwcGxpY2F0aW9uX2RhdGUpKSAlPiUNCiAgYXNfdHNpYmJsZShpbmRleCA9IGFwcGxpY2F0aW9uX2RhdGUpDQppc190c2liYmxlKGRhdGFfMTEpDQpgYGANCg0KDQpgYGB7ciBlY2hvPUZBTFNFLCBpbmNsdWRlPUZBTFNFfQ0KI0ZvciBzZWdtZW50IDEsIGludGVycG9sYXRpb24gZm9yIG1pc3NpbmcgdmFsdWVzIG9mIG51bWJlciBvZiBhcHBsaWNhbnRzDQoNCnggPC0gem9vKGRhdGFfMTEkbm9fb2ZfYXBwbGljYW50c19zdW0sZGF0YV8xMSRhcHBsaWNhdGlvbl9kYXRlKQ0KeCA8LSBhcy50cyhyb3VuZCh4KSkNCmRhdGFfMTEkbm9fb2ZfYXBwbGljYW50c19zdW0gPC0gbmEuaW50ZXJwKHJvdW5kKHgpKQ0KaXNfdHNpYmJsZShkYXRhXzExKQ0KDQoNCmBgYA0KYGBge3IgaW5jbHVkZT1GQUxTRX0NCiNGaWx0ZXIgZGF0YWZyYW1lcyBiYXNlZCBvbiBzZWdtZW50LCB0aGVuIGNvbnZlcnQgdGhlbSBpbnRvIHRzaWJibGUgZm9yIHNlZ21lbnQgMg0KZGF0YV8yMjwtZGF0YV9ncnBwICU+JSBmaWx0ZXIoc2VnbWVudCAlaW4lIGMoMikpDQpkYXRhXzIyPC1kYXRhXzIyICU+JW11dGF0ZShhcHBsaWNhdGlvbl9kYXRlID0gYXMuRGF0ZShhcHBsaWNhdGlvbl9kYXRlKSkgJT4lDQogIGFzX3RzaWJibGUoaW5kZXggPSBhcHBsaWNhdGlvbl9kYXRlKQ0KDQpgYGANCg0KDQpgYGB7ciBpbmNsdWRlPUZBTFNFfQ0KI0ZvciBzZWdtZW50IDIsIGZpbGwgZ2FwcyBmb3IgbWlzc2luZyB2YWx1ZXMNCg0KDQpoaGg8LSBkYXRhLmZyYW1lKGFwcGxpY2F0aW9uX2RhdGU9c2VxKG1pbihkYXRhXzIyJGFwcGxpY2F0aW9uX2RhdGUpLCBtYXgoZGF0YV8yMiRhcHBsaWNhdGlvbl9kYXRlKSwgYnk9ImRheXMiKSkNCmRhdGFfMjIgPC0gbWVyZ2UoZGF0YV8yMixoaCxieS54PSdhcHBsaWNhdGlvbl9kYXRlJyxieS55PSdhcHBsaWNhdGlvbl9kYXRlJyxhbGwueD1ULGFsbC55PVQpDQpkYXRhXzIyJHNlZ21lbnRbaXMubmEoZGF0YV8yMiRzZWdtZW50KV0gPC0gMQ0KZGF0YV8yMiRzZWdtZW50IDwtIE5VTEwNCmhlYWQoZGF0YV8yMikNCmRhdGFfMjI8LWRhdGFfMjIgJT4lbXV0YXRlKGFwcGxpY2F0aW9uX2RhdGUgPSBhcy5EYXRlKGFwcGxpY2F0aW9uX2RhdGUpKSAlPiUNCiAgYXNfdHNpYmJsZShpbmRleCA9IGFwcGxpY2F0aW9uX2RhdGUpDQppc190c2liYmxlKGRhdGFfMjIpDQpgYGANCg0KDQoNCmBgYHtyIGluY2x1ZGU9RkFMU0V9DQojRm9yIHNlZ21lbnQgMiwgaW50ZXJwb2xhdGlvbiBmb3IgbWlzc2luZyB2YWx1ZXMgb2YgbnVtYmVyIG9mIGFwcGxpY2FudHMNCg0KeHg8LSB6b28oZGF0YV8yMiRub19vZl9hcHBsaWNhbnRzX3N1bSxkYXRhXzIyJGFwcGxpY2F0aW9uX2RhdGUpDQp4eCA8LSBhcy50cyhyb3VuZCh4KSkNCmRhdGFfMjIkbm9fb2ZfYXBwbGljYW50c19zdW0gPC0gbmEuaW50ZXJwKHJvdW5kKHgpKQ0KaXNfdHNpYmJsZShkYXRhXzIyKQ0KDQpgYGANCg0KDQpgYGB7ciBpbmNsdWRlPSBGQUxTRX0NCnN1bShpcy5uYShkYXRhXzEpKQ0Kc3VtKGlzLm5hKGRhdGFfMikpDQpgYGANCkNoZWNraW5nIGZvciBzZWFzb25hbGl0eSwgdHJlbmQgYW5kIGN5Y2xlcw0KDQpUaGUgYmVsb3cgZ3JhcGggc2hvd3MgdGhlIG51bWJlciBvZiBhcHBsaWNhdGlvbiBhZ2FpbnN0IHRoZSB0aW1lIHBlcmlvZCBiZXR3ZWVuIDIwMTctMTkgdW5kZXIgc2VnbWVudCAxLldlIG5vdGljZSB0aGF0IHRoZSBkYXRhIHRlbmRzIHRvIGJlIHN0YXRpb25hcnkgd2l0aCBvdXRsaWVycyBpbiB0aGUgcmVnaW9uIGJldHdlZW4gMjAxNy0yMDE4LlRob3VnaCB0aGlzIGEgdmlzdWFsIGNvbmNsdXNpb24gdGhlIGh5cG90aGVzaXMgY2FuIGJlIHZhbGlkYXRlZCBieSB0ZXN0aW5nIGZvciBzdGF0aW9uYXJpdHkgdXNpbmcgdGhlIEFERihBdWdtZW50ZWQgRGlja2VyLUZ1bGxlcilUZXN0Lg0KQmV0d2VlbiB0aGUgcGVyaW9kIDIwMTctMjAxOCB3ZSBvYnNlcnZlIGEgbGluZWFyIHRyZW5kIGluIG51bWJlciBvZiBhcHBsaWNhdGlvbnMgcmVjZWl2ZWQuVGhlIHRyZW5kIGRvZXNuJ3QgcGVyc2lzdCBmb3IgYSBsb25nIHRpbWUgc2luY2UgdGhlcmUgaXMgYSBzdWRkZW4gZGVjZWxlcmF0aW9uIGluIHRoZSBudW1iZXIgb2YgYXBwbGljYXRpb25zIGR1cmluZyBBcHJpbCB0byAgTWF5LTIwMTguIFRoZSBhcHBsaWNhdGlvbnMgcmVjZWl2ZWQgZm9sbG93cyBhIGN5Y2xpY2FsIHBhdHRlcm4gd2hpY2ggYXJlIHVzdWFsbHkgZ2VuZXJhdGVkIGJ5IHRoZSBhdXRvcmVncmVzc2l2ZSBzdHJ1Y3R1cmUgb2YgdGhlIHNlcmllcy4NCmBgYHtyIGVjaG89RkFMU0V9DQoNCiMgIyAxLiBUaW1lIHBsb3RzIA0KIyANCmF1dG9wbG90KGRhdGFfMSwgbm9fb2ZfYXBwbGljYW50c19zdW0pICsNCiBsYWJzKHkgPSAiVG90YWwgbnVtYmVyIG9mIGFwcGxpY2F0aW9ucyIsDQogICAgICB0aXRsZSA9ICJOdW1iZXIgb2YgYXBwbGljYXRpb25zIGluIE5lbyBiYW5rIGZvciBTZWdtZW50IDEiKQ0KYGBgDQpgYGB7cn0NCmRhdGFfMSU+JQ0KICBnZ19zZWFzb24obm9fb2ZfYXBwbGljYW50c19zdW0sIHBlcmlvZD0ieWVhciIpICsNCiAgbGFicyh5ID0gIlRvdGFsIG51bWJlciBvZiBhcHBsaWNhdGlvbnMiLA0KICAgICAgIHRpdGxlID0gIlllYXJseSBTZWFzb25hbCBwbG90OiBOdW1iZXIgb2YgYXBwbGljYXRpb25zIGluIE5lbyBiYW5rIikNCmBgYA0KDQoNCg0KQ29tcGFyZWQgdG8gdGhlIFNlZ21lbnQgMSAsIHRoZSBudW1iZXIgb2YgYXBwbGljYXRpb25zIHJlY2VpdmVkIHVuZGVyIFNlZ21lbnQgMiBhcmUgbW9zdCBjb25zaXN0ZW50IG92ZXIgdGhlIGdpdmVuIHBlcmlvZHMgYW5kIGl0IGZvbGxvd3Mgc3RyaWN0IGN5Y2xpY2FsIHBhdHRlcm4uV2Ugb2JzZXJ2ZSBhIG1vbnRobHkgc2Vhc29uYWxpdHkgd2l0aCBoaWdoZXN0IG51bWJlciBvZiBhcHBsaWNhbnRzIGR1cmluZyB0aGUgbWlkZGxlIG9mIHRoZSBtb250aHMuDQoNCg0KDQpgYGB7cn0NCiBhdXRvcGxvdChkYXRhXzIsIG5vX29mX2FwcGxpY2FudHNfc3VtKSArDQogICBsYWJzKHkgPSAiVG90YWwgbnVtYmVyIG9mIGFwcGxpY2F0aW9ucyIsDQogICAgICAgdGl0bGUgPSAiTnVtYmVyIG9mIGFwcGxpY2F0aW9ucyBpbiBOZW8gYmFuayBmb3IgU2VnbWVudCAyIikNCmBgYA0KDQoNCmBgYHtyIGVjaG89RkFMU0Usd2FybmluZz1GQUxTRSxtZXNzYWdlPUZBTFNFLCBpbmNsdWRlPUZBTFNFfQ0KZGF0YV8xICU+JQ0KICBnZ19zZWFzb24obm9fb2ZfYXBwbGljYW50c19zdW0sIHBlcmlvZD0id2VlayIpICsNCiAgbGFicyh5ID0gIlRvdGFsIG51bWJlciBvZiBhcHBsaWNhdGlvbnMiLA0KICAgICAgIHRpdGxlID0gIldlZWtseSBTZWFzb25hbCBwbG90OiBOdW1iZXIgb2YgYXBwbGljYXRpb25zIGluIE5lbyBiYW5rIikNCmBgYA0KYGBge3IgaW5jbHVkZT1GQUxTRX0NCmRhdGFfMiAlPiUNCiAgZ2dfc2Vhc29uKG5vX29mX2FwcGxpY2FudHNfc3VtLCBwZXJpb2Q9IndlZWsiKSArDQogIGxhYnMoeSA9ICJUb3RhbCBudW1iZXIgb2YgYXBwbGljYXRpb25zIiwNCiAgICAgICB0aXRsZSA9ICJXZWVrbHkgU2Vhc29uYWwgcGxvdDogTnVtYmVyIG9mIGFwcGxpY2F0aW9ucyBpbiBOZW8gYmFuayIpDQpgYGANCg0KDQpgYGB7cn0NCiMgYikgWWVhcmx5IHNlYXNvbmFsaXR5DQoNCnRyYWluX3RzICU+JQ0KICBnZ19zZWFzb24obm9fb2ZfYXBwbGljYW50cywgcGVyaW9kPSJ5ZWFyIikgKw0KICBsYWJzKHkgPSAiVG90YWwgbnVtYmVyIG9mIGFwcGxpY2F0aW9ucyIsDQogICAgICAgdGl0bGUgPSAiWWVhcmx5IFNlYXNvbmFsIHBsb3Q6IE51bWJlciBvZiBhcHBsaWNhdGlvbnMgaW4gTmVvIGJhbmsiKQ0KYGBgDQoNCg0KYGBge3J9DQpkYXRhXzIlPiUNCiAgZ2dfc2Vhc29uKG5vX29mX2FwcGxpY2FudHNfc3VtLCBwZXJpb2Q9InllYXIiKSArDQogIGxhYnMoeSA9ICJUb3RhbCBudW1iZXIgb2YgYXBwbGljYXRpb25zIiwNCiAgICAgICB0aXRsZSA9ICJZZWFybHkgU2Vhc29uYWwgcGxvdDogTnVtYmVyIG9mIGFwcGxpY2F0aW9ucyBpbiBOZW8gYmFuayIpDQpgYGANClRoZSBhYm92ZSBncmFwaCBzaG93cyB0aGUgY3ljbGljYWwgbmF0dXJlIG9mIHRoZSBkYXRhIGFjcm9zcyB0aGUgbW9udGhzIGZvciAyMDE3IHRvIDIwMTkuIA0KYGBge3J9DQojICMgMy4gU2Vhc29uYWwgc3ViIHNlcmllcyBwbG90cw0KIyANCiMgb3B0aW9ucyhyZXByLnBsb3Qud2lkdGg9NTcgLHJlcHIucGxvdC5oZWlnaHQ9IDEwKQ0KIyBkYXRhXzEgJT4lDQojICAgZ2dfc3Vic2VyaWVzKG5vX29mX2FwcGxpY2FudHNfc3VtKSArDQojICAgbGFicygNCiMgICAgIHkgPSAiVG90YWwgbnVtYmVyIG9mIGFwcGxpY2F0aW9ucyIsDQojICAgICB0aXRsZSA9ICJOdW1iZXIgb2YgYXBwbGljYXRpb25zIGluIE5lbyBiYW5rIg0KIyAgICkNCg0KI1NlZ21lbnQrIFpvbmUgDQpnZ3Bsb3QoU2VnbWVudDEsIGFlcyh4ID0gYXBwbGljYXRpb25fZGF0ZSwgeSA9IG5vX29mX2FwcGxpY2FudHMpKSArDQpnZW9tX2xpbmUoKSArDQpmYWNldF93cmFwKCB+IHNlZ21lbnQgKyB6b25lLCBzY2FsZXMgPSAiZnJlZV95IiwgbmNvbCA9IDUpKw0KdGhlbWUoYXhpcy50ZXh0Lng9ZWxlbWVudF90ZXh0KGFuZ2xlPTkwKSkNCmBgYA0KRnJvbSB0aGUgZGF0YSB3ZSBvYnNlcnZlIHRoZSBrZXkgcmVnaW9uIGZvciBtYXhpbXVtIG5vLm9mIGFwcGxpY2F0aW9ucyBOb3J0aCBmb3IgdGhlIGZ1dHVyZSB3aGVyZSB0aGUgYmFuayBtYXkgZXhwZWN0IGhpZ2hlciBhcHBsaWNhdGlvbnMuDQoNCmBgYHtyfQ0KIyBkYXRhXzIgJT4lDQojICAgZ2dfc3Vic2VyaWVzKG5vX29mX2FwcGxpY2FudHNfc3VtKSArDQojICAgbGFicygNCiMgICAgIHkgPSAiVG90YWwgbnVtYmVyIG9mIGFwcGxpY2F0aW9ucyIsDQojICAgICB0aXRsZSA9ICJOdW1iZXIgb2YgYXBwbGljYXRpb25zIGluIE5lbyBiYW5rIg0KIyAgICkNCg0KbW9udGhfc3VtbWFyeSA8LVNlZ21lbnQxICU+JSANCiAgICAgICAgICAgICAgICAgICAgZ3JvdXBfYnkoTW9udGgpICU+JQ0KICAgICAgICAgICAgICAgICAgICBzdW1tYXJpc2Uobm9fb2ZfYXBwbGljYW50cz0gc3VtKG5vX29mX2FwcGxpY2FudHMpLC5ncm91cHM9J2Ryb3AnKSANCm1vbnRoX3N1bW1hcnkgJT4lDQogICAgICAgICBnZ3Bsb3QoYWVzKHggPSByZW9yZGVyKE1vbnRoLCBub19vZl9hcHBsaWNhbnRzKSwgeSA9IG5vX29mX2FwcGxpY2FudHMsIGZpbGwgPSBNb250aCkpICsNCiAgICAgICAgIGdlb21fY29sKCkgKw0KICAgICAgICAgc2NhbGVfZmlsbF9ocF9kKG9wdGlvbiA9ICJSb25XZWFzbGV5IikgKw0KICAgICAgICAgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZSA9ICJTZXQzIikgKw0KICAgICAgICAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgMzAwMDAwKSwgZXhwYW5kID0gYygwLDApKSArDQogICAgICAgICBsYWJzKHRpdGxlID0gIlRvdGFsIG51bWJlciBvZiBhcHBsaWNhbnRzIGluICBlYWNoIG1vbnRoIiwgeCA9ICJNb250aCIsIHkgPSAiVG90YWwgYXBwbGljYW50cyIpICsNCiAgICAgICAgIHRoZW1lX2NsYXNzaWMoKSANCmBgYA0KV2Ugb2JzZXJ2ZSB0aGF0IHRoZSBiYW5rIHJlY2VpdmVzIHRoZSBoaWdoZXN0IG51bWJlciBvZiBhcHBsaWNhdGlvbnMgaW4gT2N0b2JlciBhY3Jvc3MgdGhlIHRocmVlIHllYXJzLiBUaG91Z2ggbWF5IHZhcnkgcmVnaW9uIHdpc2UgYW5kIHN0YXRlIHdpc2UuV2Ugb2JzZXJ2ZSBtYXhpbXVtIGJhbmtpbmcgYWN0aXZpdHkgc3RhcnRpbmcgZnJvbSBlbmQgb2YgdGhlIGZpbmFuY2lhbCB5ZWFyLg0KDQpgYGB7ciBpbmNsdWRlPUZBTFNFfQ0KZ2dwbG90KHRyYWluLCBhZXMoeD0oSG9saWRheSksIGZpbGw9KEhvbGlkYXkpICkpICsNCmdlb21fYmFyKCkgKw0Kc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZSA9ICJTZXQzIikgKw0KbGFicyh4PSdIb2xpZGF5Jyx5PSdOdW1iZXIgb2YgQXBwbGljYXRpb25zJykgKw0KdGhlbWVfbWluaW1hbCgpKw0KdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIikNCmBgYA0KDQpgYGB7cn0NCmRhdGElPiUNCiAgcGl2b3Rfd2lkZXIodmFsdWVzX2Zyb209bm9fb2ZfYXBwbGljYW50cywgbmFtZXNfZnJvbT1zdGF0ZSklPiUgDQogIEdHYWxseTo6Z2dwYWlycyhjb2x1bW5zID0gMjo5KQ0KYGBgDQoNCg0KDQojIDUuIExhZyBwbG90cw0KYGBge3IgZWNobz1GQUxTRSxpbmNsdWRlPUZBTFNFfQ0Kb3B0aW9ucyhyZXByLnBsb3Qud2lkdGg9NTAgLHJlcHIucGxvdC5oZWlnaHQ9IDEwKQ0KZGF0YV8xICU+JQ0KICBnZ19sYWcobm9fb2ZfYXBwbGljYW50c19zdW0sIGdlb20gPSAicG9pbnQiKSArDQogIGxhYnMoeCA9ICJsYWcoVG90YWwgbnVtYmVyIG9mIGFwcGxpY2F0aW9ucywgaykiKQ0KDQpgYGANCg0KYGBge3IgZWNobz1GQUxTRSxpbmNsdWRlPUZBTFNFfQ0KZGF0YV8yICU+JQ0KICBnZ19sYWcobm9fb2ZfYXBwbGljYW50c19zdW0sIGdlb20gPSAicG9pbnQiKSArDQogIGxhYnMoeCA9ICJsYWcoVG90YWwgbnVtYmVyIG9mIGFwcGxpY2F0aW9ucywgaykiKQ0KYGBgDQoNCj4gQ09NUE9ORU5UUyBPRiBUSEUgVElNRSBTRVJJRVMgRk9SIEVBQ0ggU0VHTUVOVA0KDQpXZSBhdHRlbXB0IHRvIGFuYWx5emUgdGhyZWUgbWFpbiBjb21wb25lbnRzIG9mIHRoZSB0aW1lIHNlcmllcyB0byBhbmFseXplIGhvdyB0aGV5IGJlaGF2ZSBvdmVyIHRpbWUtDQoNCj4gU2Vhc29uYWwgQ29tcG9uZW50DQoNCj4gVHJlbmQgQ3ljbGUgQ29tcG9uZW50DQoNCj4gUmVtYWluZGVyIENvbXBvbmVudA0KDQoNCg0KPlNFR01FTlQxDQoNCkZvciBTZWdtZW50IDEgd2Ugb2JzZXJ2ZSBhIGxpbmVhciB0cmVuZCBmcm9tIHRoZSB0aW1lIHBlcmlvZCAyMDE3IHRvIDIwMTkuVGhlcmUgaXMgYW4gaW5jb25zaXN0ZW50IHllYXJseSBzZWFzb25hbGl0eSBzaW5jZSB0aGUgZ2FwcyBhcmUgd2lkZSBhdCAgY2VydGFpbiBwb2ludHMuVGhyb3VnaG91dCB0aGUgeWVhciB3ZSBzZWUgb3V0bGllcnMgbWFpbmx5IGluIHRoZSBRdWFydGVyIDMuVGhlIHllYXJseSBzZWFzb25hbGl0eSBzaG93cyB0aGF0IHRoZSBwZWFrIGJ1c2luZXNzIHBlcmlvZCB0byBiZSBtYWlubHkgaW4gdGhlIG1vbnRocyBvZiBBdWd1c3QtU2VwdGVtYmVyLU9jdG9iZXItTm92ZW1iZXIgZm9yIFNlZ21lbnQgMSBjdXN0b21lcnMuVGhlIHJlc2lkdWFsIHBhcnQgcmVtb3ZlcyB0aGUgcmVzaWR1YWwgYW5kIHRyZW5kIGNvbXBvbmVudCBmcm9tIHRoZSBkYXRhIGFuZCBzZWFzb25hbGx5IGFkanVzdGVkIGRhdGEgc2hvd3MgYSAgdmFyaWF0aW9uIGluIHRoZSBudW1iZXIgb2YgYXBwbGljYXRpb24gcmVjZWl2ZWQgdGh1cyB0aGUgc2Vhc29uYWxpdHkgcGxheXMgYSBtYWpvciByb2xlIGluIHRoZSBidXNpbmVzcyBwcm9ibGVtIHVuZGVyIGNvbnNpZGVyYXRpb24gZm9yIFNlZ21lbnQgMSBjdXN0b21lcnMuDQoNCmBgYHtyIGluY2x1ZGU9RkFMU0V9DQpkY21wIDwtIGRhdGFfMSU+JQ0KICBtb2RlbChzdGwgPSBTVEwobm9fb2ZfYXBwbGljYW50c19zdW0pKQ0KYGBgDQoNCg0KYGBge3IgZWNobz1GQUxTRX0NCmNvbXBvbmVudHMoZGNtcCkgJT4lIGF1dG9wbG90KCkNCg0KYGBgDQoNCg0KYGBge3IgaW5jbHVkZT1GQUxTRX0NCmRjbXAgPC0gZGF0YV8yJT4lDQogIG1vZGVsKHN0bCA9IFNUTChub19vZl9hcHBsaWNhbnRzX3N1bSkpDQpgYGANCg0KPiBTRUdNRU5UIDINCg0KYGBge3J9DQpjb21wb25lbnRzKGRjbXApICU+JSBhdXRvcGxvdCgpDQpgYGANCg0KT24gZGVjb21wb3NpbmcgdGhlIGRhdGEgdW5kZXIgU2VnbWVudCAyIHdlIG9ic2VydmUgdGhhdCB0aGVyZSBpcyBhIG1vbnRobHkgc2Vhc29uYWxpdHkgd2Ugb2JzZXJ2ZSB0aHJvdWdoIG91dCB0aGUgeWVhcnMuIFRoZSB3ZWVrbHkgc2Vhc29uYWxpdHkgaXMgYWxzbyBzaWduaWZpY2FudCBzaW5jZSB0aGUgZ2FwcyBhcmUgbmVpdGhlciBjbG9zZSBieSBub3Igd2lkZS4gVGhlIHRyZW5kIHRoYXQgd2Ugb2JzZXJ2ZSBpcyBtb3N0bHkgaG9yaXpvbnRhbCB0aHJvdWdoIGVhY2ggeWVhciBhbmQgdGVuZHMgdG8gaGF2ZSBhIGxvbmcgdGVybSB1cHdhcmQgdHJlbmQgZnJvbSAyMDE3IHRocm91Z2ggMjAxOCBmcm9tIDIwMTggd2Ugb2JzZXJ2ZSBhIGRvd253YXJkIHRyZW5kLk9uIHJlbW92aW5nIHRoZSBzZWFzb25hbGl0eSBhbmQgdHJlbmQgdGhlIHNlYXNvbmFsbHkgYWRqdXN0ZWQgZGF0YSBzaG93cyBtb3JlIG51bWJlciBvZiBjaGFuZ2luZyBsZXZlbHMvcG9pbnRzLg0KDQojIENIT0lDRSBPRiBNT0RFTFMNCg0KDQoNCiMgQUNGIGFuZCBQQUNGIHBsb3RzDQoNCg0KSWYgdGhlIGF1dG9jb3JyZWxhdGlvbiBwbG90IG9mIGFjZiBjcm9zc2VzIHRoZSBkYXNoZWQgYmx1ZSBsaW5lLCBpdCBtZWFucyB0aGF0IHNwZWNpZmljIGxhZyBpcyBzaWduaWZpY2FudGx5IGNvcnJlbGF0ZWQgd2l0aCBjdXJyZW50IHNlcmllcy4NCg0KRnJvbSBoZXJlLCB3ZSBjYW4gb2JzZXJ2ZSB0aGF0IHRoZXJlIGlzIGFwcHJveCBwZWFrIGF0IDAsMzAsNjAsOTAuLi4gbGFncy4gVGhlIG1heGltdW0gYXQgbGFnIDAsMzAsNjAuLiBpbmRpY2F0ZXMgYSBwb3NpdGl2ZSByZWxhdGlvbnNoaXAgd2l0aCBtb250aGx5IGN5Y2xlLg0KDQpIZXJlLCBpbnN0ZWFkIG9mIHRhaWxpbmctb2ZmIGlmIHRoZXJlIGlzIGEgc2xvdyBkZWNheSB3ZSBjYW4gc2F5IGl0IHRvIGJlIGEgbm9uLSBzdGF0aW9uYXJ5IHNlcmllcy4gRXhhbWluaW5nIEFDRiBhbmQgUEFDRiBoZWxwcyB1cyB0byBlc3RpbWF0ZSBwbGF1c2libGUgbW9kZWxzIGFuZCBzZWxlY3QgcCxkIGFuZCBxLiBEaWZmZXJlbmNpbmcgbWF5IGJlIG5lZWRlZCBpZiB0aGVyZSBpcyBzbG93LSBkZWNheSBpbiB0aGUgQUNGLiBTZXZlcmFsIG1vZGVscyBtYXkgbmVlZCB0byBiZSBlc3RpbWF0ZWQuIFNvLCBoZXJlIHdlIHdpbGwgdHJ5IG91dCBkaWZmZXJlbnQgY29tYmluYXRpb25zIG9mIHAsZCBhbmQgcSB0byBnZXQgbW9kZWwgd2l0aCBsb3dlciBBSUMgb3IgQklDIHNjb3JlLiBBSUMgYW5kIEJJQyBhcmUgdHdvIG1lYXN1cmVzIG9mIGdvb2RuZXNzIG9mIGZpdC4gVGhleSBtZWFzdXJlIHRoZSB0cmFkZS1vZmYgYmV0d2VlbiBtb2RlbCBmaXQgYW5kIGNvbXBsZXhpdHkgb2YgZGF0YS4gQSBsb3dlciBBSUMgb3IgQklDIHZhbHVlIGluZGljYXRlcyBhIGJldHRlciBmaXQuDQoNCmBgYHtyIGVjaG89RkFMU0V9DQpwYXIobWZyb3c9YygyLDIpKQ0KYT1kYXRhXzEgJT4lIHRzaWJibGU6OmZpbGxfZ2FwcygpICU+JQ0KICBBQ0Yobm9fb2ZfYXBwbGljYW50c19zdW0pICU+JQ0KICBhdXRvcGxvdCgpICsNCiAgbGFicyh0aXRsZT0iQUNGIGZvciBTZWdtZW50IDEiKQ0KDQpiPWRhdGFfMSAlPiUgdHNpYmJsZTo6ZmlsbF9nYXBzKCkgJT4lDQogIFBBQ0Yobm9fb2ZfYXBwbGljYW50c19zdW0pICU+JQ0KICBhdXRvcGxvdCgpICsNCiAgbGFicyh0aXRsZT0iUEFDRiBmb3IgU2VnbWVudCAxIikNCg0KYz1kYXRhXzIgJT4lIHRzaWJibGU6OmZpbGxfZ2FwcygpICU+JQ0KICBBQ0Yobm9fb2ZfYXBwbGljYW50c19zdW0pICU+JQ0KICBhdXRvcGxvdCgpICsNCiAgbGFicyh0aXRsZT0iQUNGIGZvciBTZWdtZW50IDIiKQ0KDQpkPWRhdGFfMiAlPiUgdHNpYmJsZTo6ZmlsbF9nYXBzKCkgJT4lDQogIFBBQ0Yobm9fb2ZfYXBwbGljYW50c19zdW0pICU+JQ0KICBhdXRvcGxvdCgpICsNCiAgbGFicyh0aXRsZT0iUEFDRmZvciBTZWdtZW50IDIiKQ0KDQpgYGANCmBgYHtyfQ0KI2luc3RhbGwucGFja2FnZXMoJ3BhdGNod29yaycpDQpsaWJyYXJ5KHBhdGNod29yaykNCg0KYSsgYiArYyArZA0KDQpgYGANCg0KI1RTTE0gTW9kZWxpbmcNCg0KVFNMTSBtb2RlbGluZzogSW4gdGhpcyBjYXNlIHRoZSBtb2RlbCBmdW5jdGlvbiBpcyBUU0xNKCkgKHRpbWUgc2VyaWVzIGxpbmVhciBtb2RlbCksIHRoZSByZXNwb25zZSB2YXJpYWJsZSBpcyBub19vZl9hcHBsaWNhbnRzIGFuZCBpdCBpcyBiZWluZyBtb2RlbGVkIHVzaW5nIHRyZW5kKCkgKGEg4oCcc3BlY2lhbOKAnSBmdW5jdGlvbiBzcGVjaWZ5aW5nIGEgbGluZWFyIHRyZW5kIHdoZW4gaXQgaXMgdXNlZCB3aXRoaW4gVFNMTSgpKS4NCkZpcnN0IG9mIGFsbCBsaW5lYXIgbW9kZWwgb24gc2VnbWVudCAxIGlzIGFwcGxpZWQuDQoNCmBgYHtyIGVjaG89RmFsc2V9DQpmaXQgPC0gZGF0YV8xICU+JQ0KICBtb2RlbCh0cmVuZF9tb2RlbCA9IFRTTE0obm9fb2ZfYXBwbGljYW50c19zdW0gfiB0cmVuZCgpKSkNCmZpdCAlPiUgZm9yZWNhc3QoaCA9IDMwKQ0KYGBgDQoNCg0KYGBge3IgZWNobz1GYWxzZX0NCmZpdCAlPiUNCiAgZm9yZWNhc3QoaCA9IDMwKSAlPiUNCiAgYXV0b3Bsb3QoZGF0YV8xKQ0KZm9yZTwtZml0ICU+JSBmb3JlY2FzdChoPTMwKQ0KYGBgDQogIA0KICANCkhlcmUsIHdlIGNhbiBvYnNlcnZlIGFwcHJveCB2YWx1ZSBvZiBmdXR1cmUgcHJlZGljdGlvbnMgZm9yIG5leHQgMzAgZGF5cy4NCg0KTmV4dCwgc2FtZSBwcm9jZXNzIGlzIGFwcGxpZWQgb24gc2VnbWVudCAyIGRhdGFzZXQsIGFuZCBhcHByb3ggbnVtYmVyIG9mIGFwcGxpY2FudHMgaXMgb2JzZXJ2ZWQuDQoNCg0KYGBge3IgZWNobz1GYWxzZX0NCmZpdCA8LSBkYXRhXzIgJT4lDQogIG1vZGVsKHRyZW5kX21vZGVsID0gVFNMTShub19vZl9hcHBsaWNhbnRzX3N1bSB+IHRyZW5kKCkpKQ0KZml0ICU+JSBmb3JlY2FzdChoID0gMzApDQpgYGANCg0KDQpgYGB7ciBlY2hvPUZhbHNlfQ0KZml0ICU+JQ0KICBmb3JlY2FzdChoID0gMzApICU+JQ0KICBhdXRvcGxvdChkYXRhXzIpDQpmb3JlMTwtZml0ICU+JSBmb3JlY2FzdChoPTMwKQ0KYGBgDQpGcm9tIGhlcmUsIHdlIGNhbiBvYnNlcnZlIGFwcHJveCB2YWx1ZXMgb2YgbnVtYmVyIG9mIGFwcGxpY2FudHMgZm9yIG5leHQgMzAgZGF5cyBmb3Igc2VnbWVudCAyLiBFYWNoIHJvdyBjb3JyZXNwb25kcyB0byBvbmUgZm9yZWNhc3QgcGVyaW9kIGZvciBlYWNoIGRheS4gVGhlIG5vX29mX2FwcGxpY2FudHMgY29sdW1uIGNvbnRhaW5zIHRoZSBmb3JlY2FzdCBkaXN0cmlidXRpb24sIHdoaWxlIHRoZSAubWVhbiBjb2x1bW4gY29udGFpbnMgdGhlIHBvaW50IGZvcmVjYXN0LiBUaGUgcG9pbnQgZm9yZWNhc3QgaXMgdGhlIG1lYW4gKG9yIGF2ZXJhZ2UpIG9mIHRoZSBmb3JlY2FzdCBkaXN0cmlidXRpb24uDQoNCmBgYHtyIGVjaG89RkFMU0V9DQoNCmRmX3MgPC0gZGF0YS5mcmFtZShpZCA9IGMoMTo2MCksDQogICAgICAgICAgICAgICAgIG5vX29mX2FwcGxpY2FudHMgPSBjKHRhaWwoZm9yZSQubWVhbiwzMCksIHRhaWwoZm9yZTEkLm1lYW4sMzApKQ0KICAgICAgICAgICAgICAgICApDQp3cml0ZS5jc3YoZGZfcywiIiwgcm93Lm5hbWVzID0gRkFMU0UpDQpgYGANCg0KRmluYWxseSwgd2UgY29tYmluZSBkYXRhc2V0IGZvciBuZXh0IDMwIGRheXMgZm9yIHNlZ21lbnQgMSBhbmQgMi4NCg0KIyBEaWNrZXkgZnVsbGVyIHRlc3QNCg0KYGBge3IgZWNobz1GQUxTRX0NCmFkZi50ZXN0KGRhdGFfMSRub19vZl9hcHBsaWNhbnRzX3N1bSkNCmBgYA0KSGVyZSwgbnVsbCBoeXBvdGhlc2lzIGlzIHRoYXQgdGltZSBzZXJpZXMgaXMgbm90IHN0YXRpb25hcnkuSWYgbnVsbCBoeXBvdGhlc2lzIGlzIHJlamVjdGVkLCB0aGVuIHRhcmdldCB2YXJpYWJsZSBpcyBzdGF0aW9uYXJ5LiBJZiBpdCdzIG5vdCByZWplY3RlZCwgd2Ugc2hvdWxkIGRvIGRpZmZlcmVuY2luZyBhbmQgdGhlbiBwZXJmb3JtIGRpY2tleS1mdWxsZXIgdGVzdCBhZ2Fpbi4gSGVyZSwgcC12YWx1ZSBpcyBsZXNzIHRoYW4gMC4wNSwgc28gd2UgY2FuIHJlamVjdCBudWxsIGh5cG90aGVzaXMgYW5kIHNheSB0aGF0IHNlcmllcyBpcyBzdGF0aW9uYXJ5IGVub3VnaCB0byBkbyBhbnkga2luZCBvZiB0aW1lIHNlcmllcyBtb2RlbGluZy4NCg0KDQojQVINCkluIG9yZGVyIHRvIGZpdCB0aGUgQVIgbW9kZWwsIHdlIGhhdmUgaW5pdGlhbGx5IGNvbnZlcnRlZCB0aGUgbnVtYmVyIG9mIGFwcGxpY2FudHMNCmNvbHVtbiB0byBhIHZlY3Rvci4gVG8gc2VlIHRoZSBsYWcgdmFsdWUgdG8gYmUgdXNlZCBpbiB0aGUgQVIgbW9kZWwsIHdlIGhhdmUgdXNlZA0KdGhlIGFib3ZlIGZ1bmN0aW9uIHRoYXQgaGFzIGdpdmVuIGEgdmFsdWUgb2YgNy4NCkhlbmNlLCB3ZSBmaXQgYSBBUig3KSBtb2RlbC4NCg0KYGBge3IgZWNobz1GQUxTRSwgaW5jbHVkZT1GQUxTRX0NCiBkYXRhX3ZlYyA8LSBhcy52ZWN0b3IoZGF0YV8xWyJub19vZl9hcHBsaWNhbnRzX3N1bSJdKQ0KIGRhdGFfdmVjLmFyIDwtIGFyKGRhdGFfdmVjJG5vX29mX2FwcGxpY2FudHNfc3VtLCBtZXRob2QgPSAibWxlIikNCiBkYXRhX3ZlYy5hciRvcmRlcg0KDQpgYGANCmBgYHtyIGluY2x1ZGU9RkFMU0V9DQpkYXRhX3ZlYy5hciRhcg0KYGBgDQpgYGB7ciBpbmNsdWRlPUZBTFNFfQ0Kc2VnMV9hcjwtYXJpbWEoZGF0YV92ZWMkbm9fb2ZfYXBwbGljYW50c19zdW0sYyg3LDAsMCkpDQpzZWcxX2ZvcmVjYXN0IDwtIHByZWRpY3Qoc2VnMV9hciwgbi5haGVhZCA9IDMwKQ0Kc2VnMV9mb3JlY2FzdF92YWx1ZXMgPC0gc2VnMV9mb3JlY2FzdCRwcmVkDQpzZWcxX2ZvcmVjYXN0X3ZhbHVlcw0KYGBgDQpVc2luZyB0aGUgcHJlZGljdCBmdW5jdGlvbiwgdGhlIHRvdGFsIG51bWJlciBvZiBhcHBsaWNhdGlvbnMgZm9yIHRoZSBuZXh0IDMwIGRheXMNCmlzIGZvcmVjYXN0ZWQuIFRoZSAoNywwLDApIGNvbXBvbmVudCBpbiBhcmltYSBmdW5jdGlvbiBpcyBzYW1lIGFzIGZpdHRpbmcgYQ0KN3RoIG9yZGVyIEF1dG9yZWdyZXNzaXZlIG1vZGVsLiBUaGUgQUlDIHNjb3JlIGZvciBzZWdtZW50IDEgZGF0YSBpcyBlcXVhbCB0bw0KYGBge3J9DQpBSUMoc2VnMV9hcikNCmBgYA0KDQpUaGUgc3RlcHMgYXJlIHNpbWlsYXJseSBmb2xsb3dlZCBmb3Igc2VnbWVudCAyIGRhdGEgYXMgd2VsbC4gVGhlIEFJQyBzY29yZSBmb3INClNlZ21lbnQgMiBpcyBmb3VuZCB0byBiZSANCmBgYHtyIGVjaG89RkFMU0UsIGluY2x1ZGU9RkFMU0V9DQpzZWcyX2FyPC1hcmltYShkYXRhXzIkbm9fb2ZfYXBwbGljYW50c19zdW0sYyg3LDAsMCkpDQpzZWcyX2ZvcmVjYXN0IDwtIHByZWRpY3Qoc2VnMl9hciwgbi5haGVhZCA9IDMwKQ0Kc2VnMl9mb3JlY2FzdF92YWx1ZXMgPC0gc2VnMl9mb3JlY2FzdCRwcmVkDQpzZWcyX2ZvcmVjYXN0X3ZhbHVlcw0KDQpgYGANCmBgYHtyIGVjaG89RkFMU0V9DQpBSUMoc2VnMl9hcikNCg0KYGBgDQojIEFyaW1hIE1vZGVsaW5nDQoNCldoaWxlIGV4cG9uZW50aWFsIHNtb290aGluZyBtb2RlbHMgYXJlIGJhc2VkIG9uIGEgZGVzY3JpcHRpb24gb2YgdGhlIHRyZW5kIGFuZCBzZWFzb25hbGl0eSBpbiB0aGUgZGF0YSwgQVJJTUEgbW9kZWxzIGFpbSB0byBkZXNjcmliZSB0aGUgYXV0b2NvcnJlbGF0aW9ucyBpbiB0aGUgZGF0YS4gV2hpdGUgbm9pc2UgZGVzY3JpYmVzIHRoZSBhc3N1bXB0aW9uIHRoYXQgZWFjaCBlbGVtZW50IGluIGEgc2VyaWVzIGlzIGEgcmFuZG9tIGRyYXcgZnJvbSBhIHBvcHVsYXRpb24gd2l0aCB6ZXJvIG1lYW4gYW5kIGNvbnN0YW50IHZhcmlhbmNlLiBBdXRvcmVncmVzc2l2ZShBUikgYW5kIG1vdmluZyBhdmVyYWdlKE1BKSBtb2RlbHMgY29ycmVjdCBmb3IgdmlvbGF0aW9ucyBvZiB0aGlzIHdoaXRlIG5vaXNlIGFzc3VtcHRpb24uDQoNCkFzIG91ciBtb2RlbCBzYXRpc2ZpZXMgc3RhdGlvbmFyaXR5LCB3ZSBtb3ZlIG9uIHRvIGFwcGx5aW5nIGFyaW1hIG1vZGVsaW5nIG9uIGl0LiANCiMjIEFwcGx5aW5nIGFyaW1hIG1vZGVsaW5nIG9uIHNlZ21lbnQgMQ0KYGBge3IgZWNobz1GQUxTRX0NCmZpdCA8LSBkYXRhXzEgJT4lDQogIG1vZGVsKEFSSU1BKG5vX29mX2FwcGxpY2FudHNfc3VtKSkNCnJlcG9ydChmaXQpDQpgYGANCg0KYGBge3IgZWNobz1GYWxzZX0NCmZpdCAlPiUgZm9yZWNhc3QoaD0zMCkgJT4lDQogIGF1dG9wbG90KGRhdGFfMSkNCmZvcmU8LWZpdCAlPiUgZm9yZWNhc3QoaD0zMCkNCmBgYA0KDQoNCiMjIEFwcGx5aW5nIGFyaW1hIG1vZGVsaW5nIG9uIHNlZ21lbnQgMg0KYGBge3IgZWNobz1GQUxTRX0NCmZpdCA8LSBkYXRhXzIgJT4lDQogIG1vZGVsKEFSSU1BKG5vX29mX2FwcGxpY2FudHNfc3VtKSkNCnJlcG9ydChmaXQpDQpgYGANCg0KYGBge3IgZWNobz1GYWxzZX0NCmZpdCAlPiUgZm9yZWNhc3QoaD0zMCkgJT4lDQogIGF1dG9wbG90KGRhdGFfMikNCmZvcmUxPC1maXQgJT4lIGZvcmVjYXN0KGg9MzApDQpgYGANCg0KYGBge3IgZWNobz1GQUxTRX0NCg0KZGZfcyA8LSBkYXRhLmZyYW1lKGlkID0gYygxOjYwKSwNCiAgICAgICAgICAgICAgICAgbm9fb2ZfYXBwbGljYW50cyA9IGModGFpbChmb3JlJC5tZWFuLDMwKSwgdGFpbChmb3JlMSQubWVhbiwzMCkpDQogICAgICAgICAgICAgICAgICkNCndyaXRlLmNzdihkZl9zLCJDOlxcVXNlcnNcXGFzdXNcXERlc2t0b3BcXENvbGxlZ2VcXDNyZCBzZW1lc3RlclxcVGltZSBzZXJpZXMtQWtoaWxlc2h3YXJcXGFyaW1hX2ZpbmFsLmNzdiIsIHJvdy5uYW1lcyA9IEZBTFNFKQ0KDQpgYGANCkhlcmUsIHdlIG9ic2VydmUgdGhhdCB3ZSBnZXQgYmV0dGVyIHByZWRpY3Rpb25zIGZyb20gQVJJTUEgdGhhbiB3ZSBnb3QgZnJvbSBUU0xNIG1vZGVsLiBUaGlzIGNhbiBiZSBvYnNlcnZlZCBmcm9tIHBsb3RzIGFzIHdlbGwuDQoNCiMgQVJJTUEgKFdpdGhvdXQgc2Vhc29uYWxpdHkpDQoNClRob3VnaCB3ZSBnb3Qgb3VyIGRhdGEgYXMgc3RhdGlvbmFyeSwgYnV0IHBsb3RzIGFwcGVhcmVkIHRvIGhhdmUgc29tZSBzb3J0IG9mIHNlYXNvbmFsaXR5LiBTbywgd2Ugd2VudCBhaGVhZCB0byB1c2UgYXJpbWEgYnkgcmVtb3Zpbmcgc2Vhc29uYWxpdHkuDQpJbiBzZWdtZW50IDENCg0KYGBge3IgZWNobz1GQUxTRX0NCnN0bFRyYWluID0gc3RsKGRhdGFfMTEscy53aW5kb3c9InBlcmlvZGljIikNCnRzVHJhaW5XaXRob3V0U2Vhc29uYWwgPSBzdGxUcmFpbiR0aW1lLnNlcmllc1ssMl0rc3RsVHJhaW4kdGltZS5zZXJpZXNbLDNdDQoNCmBgYA0KDQoNCg0KYGBge3IgZWNobz1GQUxTRX0NCmRhdGFfeDwtZGF0YV8xMSU+JW11dGF0ZShub19vZl9hcHBsaWNhbnRzX3N1bT10c1RyYWluV2l0aG91dFNlYXNvbmFsKQ0KZml0IDwtIGRhdGFfeCAlPiUNCiAgbW9kZWwoQVJJTUEobm9fb2ZfYXBwbGljYW50c19zdW0pKQ0KcmVwb3J0KGZpdCkNCmBgYA0KSGVyZSwgd2Ugb2JzZXJ2ZSB0aGF0IEFJQyBhbmQgQklDIHZhbHVlIGRlY3JlYXNlcywgd2hpY2ggc2hvd3MgdGhhdCB0aGlzIGlzIGEgYmV0dGVyIG1vZGVsIGlmIHdlIHJlbW92ZSBzZWFzb25hbGl0eS4NCg0KYGBge3IgZWNobz1GYWxzZX0NCmZpdCAlPiUgZm9yZWNhc3QoaD0zMCkgJT4lDQogIGF1dG9wbG90KGRhdGFfeCkNCmBgYA0KDQoNCg0KYGBge3IgZWNobz1GQUxTRX0NCmZvcmU8LWZpdCAlPiUgZm9yZWNhc3QoaD0zMCkNCmBgYA0KDQoNCg0KDQojIFJlbW92aW5nIHNlYXNvbmFsaXR5IGZyb20gc2VnbWVudCAyDQoNCmBgYHtyIGVjaG89RkFMU0V9DQpzdGxUcmFpbiA9IHN0bChkYXRhXzIyLHMud2luZG93PSJwZXJpb2RpYyIpDQp0c1RyYWluV2l0aG91dFNlYXNvbmFsID0gc3RsVHJhaW4kdGltZS5zZXJpZXNbLDJdK3N0bFRyYWluJHRpbWUuc2VyaWVzWywzXQ0KDQpgYGANCg0KYGBge3IgZWNobz1GQUxTRX0NCmRhdGFfeHg8LWRhdGFfMjIlPiVtdXRhdGUobm9fb2ZfYXBwbGljYW50c19zdW09dHNUcmFpbldpdGhvdXRTZWFzb25hbCkNCmZpdCA8LSBkYXRhX3h4ICU+JQ0KICBtb2RlbChBUklNQShub19vZl9hcHBsaWNhbnRzX3N1bSkpDQpyZXBvcnQoZml0KQ0KYGBgDQpIZXJlLCB3ZSBvYnNlcnZlIHRoYXQgQUlDIGFuZCBCSUMgdmFsdWUgYm90aCBkZWNyZWFzZXMgd2hlbiB3ZSByZW1vdmUgc2Vhc29uYWxpdHkgZnJvbSBkYXRhLCB3aGljaCBzaG93cyB0aGF0IHRoaXMgaXMgYSBiZXR0ZXIgbW9kZWwuDQoNCmBgYHtyIGVjaG89RmFsc2V9DQpmaXQgJT4lIGZvcmVjYXN0KGg9MzApICU+JQ0KICBhdXRvcGxvdChkYXRhX3h4KQ0KYGBgDQoNCg0KDQpgYGB7ciBlY2hvPUZBTFNFfQ0KZm9yZTE8LWZpdCAlPiUgZm9yZWNhc3QoaD0zMCkNCmRmX3MgPC0gZGF0YS5mcmFtZShpZCA9IGMoMTo2MCksDQogICAgICAgICAgICAgICAgIG5vX29mX2FwcGxpY2FudHMgPSBjKHRhaWwoZm9yZSQubWVhbiwzMCksIHRhaWwoZm9yZTEkLm1lYW4sMzApKQ0KICAgICAgICAgICAgICAgICApDQp3cml0ZS5jc3YoZGZfcywiRDpcXFRpbWVTZXJpZXNfVGFza1xcYXJpbWF3aXRob3V0c2Vhc29uX25ldy5jc3YiLCByb3cubmFtZXMgPSBGQUxTRSkNCg0KYGBgDQoNCg0KIyBDaGVja2luZyBmb3IgVHJlbmQgaW4gZGF0YQ0KDQpGaXJzdCBvZmYsIEknZCB0YWtlIHRoZSBkaWZmZXJlbmNlIG9mIHRpbWUgc2VyaWVzIHRvIGRlLXRyZW5kIGl0LCBpdCBoYXMgYSBjb25zaWRlcmFibGUgc3RvY2hhc3RpYyB0cmVuZC4gVGhlIG1vc3Qgb2J2aW91cyBzaWduIG9mIHRoaXMsIGJlc2lkZSB0aGUgdGltZSBzZXJpZXMgaGF2aW5nIGEgc3RlYWR5IHVwd2FyZCByaXNlLCBpcyB0aGF0IHRoZSBBQ0YgY29tcG9uZW50cyB0YWtlcyBhIGxvbmcgdGltZSB0byBkaWUgb3V0LiBXaGlsZSB3ZSBjYW4gZml0IGEgbW9kZWwgdG8gdGhlIGRhdGEgYXMgaXMgd2l0aCBhIGRyaWZ0IHRlcm0sIGl0J3MgbXVjaCBlYXNpZXIgdG8gcmVhZCB0aGUgQUNGIGFuZCBQQUNGIHBsb3RzIHdoZW4gdGhlIHRyZW5kIGlzbid0IHRoZXJlLiBTbywgd2UgYWxzbyB0cmllZCB0byBvdmVyY29tZSBwcmVzZW5jZSBvZiBzbWFsbCBhbW91bnQgb2YgdHJlbmQgYnkgdHdvIG1ldGhvZHMoZGlmZmVyZW5jaW5nIGFuZCByZW1vdmluZyB0cmVuZCBjb21wb25lbnQgZnJvbSBzdGwgZGVjb21wb3NpdGlvbiBhcyB3ZWxsKS4NCg0KRGF0YSBhZnRlciBkaWZmZXJlbmNpbmcNCg0KSGVyZSwgd2UgdHJ5IHRvIG9ic2VydmUgQUNGIGFuZCBQQUNGIG1vZGVsIGFmdGVyIGRpZmZlcmVuY2luZy4NCg0KYGBge3IgZWNobz1GYWxzZX0NCnRmLmQgPC0gZGlmZihkYXRhXzEkbm9fb2ZfYXBwbGljYW50c19zdW0pDQpwbG90KHRmLmQpOyBhY2YodGYuZCwgbWFpbj0iIik7IHBhY2YodGYuZCwgbWFpbj0iIikNCiNwYWNmKGRhdGFfMSRub19vZl9hcHBsaWNhbnRzX3N1bSkNCmBgYA0KDQoNCg0KYGBge3IgZWNobz1GYWxzZX0NCmRhdGFfMSAlPiUNCiAgZ2dfdHNkaXNwbGF5KGRpZmZlcmVuY2Uobm9fb2ZfYXBwbGljYW50c19zdW0pLCBwbG90X3R5cGU9J3BhcnRpYWwnKQ0KYGBgDQoNCkZ1cnRoZXIsIHdlIGp1c3Qgd29yayBvbiByZW1haW5kZXIgdGltZSBzZXJpZXMsIGJ5IHJlbW92aW5nIHRyZW5kIGFuZCBzZWFzb25hbGl0eS4NCg0KIyBSZW1vdmluZyB0cmVuZCBhbmQgc2Vhc29uYWxpdHkgZnJvbSBkYXRhDQpXZSBzdGFydCB3aXRoIHNlZ21lbnQgMQ0KDQpgYGB7ciBlY2hvPUZBTFNFfQ0Kc3RsVHJhaW4gPSBzdGwoZGF0YV8xMSxzLndpbmRvdz0icGVyaW9kaWMiKQ0KdHNUcmFpbldpdGhvdXR0cmVuZFNlYXNvbmFsID0gc3RsVHJhaW4kdGltZS5zZXJpZXNbLDNdDQoNCmBgYA0KDQpgYGB7ciBlY2hvPUZBTFNFfQ0KZGF0YV94PC1kYXRhXzExJT4lbXV0YXRlKG5vX29mX2FwcGxpY2FudHNfc3VtPXRzVHJhaW5XaXRob3V0dHJlbmRTZWFzb25hbCkNCmZpdCA8LSBkYXRhX3ggJT4lDQogIG1vZGVsKEFSSU1BKG5vX29mX2FwcGxpY2FudHNfc3VtKSkNCnJlcG9ydChmaXQpDQpgYGANCg0KDQpgYGB7ciBlY2hvPUZhbHNlfQ0KZml0ICU+JSBmb3JlY2FzdChoPTMwKSAlPiUNCiAgYXV0b3Bsb3QoZGF0YV94KQ0KYGBgDQoNCg0KDQpgYGB7ciBlY2hvPUZBTFNFfQ0KZm9yZTwtZml0ICU+JSBmb3JlY2FzdChoPTMwKQ0KDQpgYGANCg0KDQpGb3Igc2VnbWVudCAyDQoNCmBgYHtyIGVjaG89RkFMU0V9DQpzdGxUcmFpbiA9IHN0bChkYXRhXzIyLHMud2luZG93PSJwZXJpb2RpYyIpDQp0c1RyYWluV2l0aG91dHRyZW5kU2Vhc29uYWwgPSBzdGxUcmFpbiR0aW1lLnNlcmllc1ssM10NCmBgYA0KDQpgYGB7ciBlY2hvPUZBTFNFfQ0KZGF0YV94eDwtZGF0YV8yMiU+JW11dGF0ZShub19vZl9hcHBsaWNhbnRzX3N1bT10c1RyYWluV2l0aG91dHRyZW5kU2Vhc29uYWwpDQpmaXQgPC0gZGF0YV94eCAlPiUNCiAgbW9kZWwoQVJJTUEobm9fb2ZfYXBwbGljYW50c19zdW0pKQ0KcmVwb3J0KGZpdCkNCmBgYA0KDQpgYGB7ciBlY2hvPUZhbHNlfQ0KZml0ICU+JSBmb3JlY2FzdChoPTMwKSAlPiUNCiAgYXV0b3Bsb3QoZGF0YV94eCkNCmBgYA0KDQoNCg0KYGBge3IgZWNobz1GQUxTRX0NCmZvcmUxPC1maXQgJT4lIGZvcmVjYXN0KGg9MzApDQoNCmBgYA0KYGBge3IgZWNobz1GQUxTRX0NCg0KZGZfcyA8LSBkYXRhLmZyYW1lKGlkID0gYygxOjYwKSwNCiAgICAgICAgICAgICAgICAgbm9fb2ZfYXBwbGljYW50cyA9IGModGFpbChmb3JlJC5tZWFuLDMwKSwgdGFpbChmb3JlMSQubWVhbiwzMCkpDQogICAgICAgICAgICAgICAgICkNCndyaXRlLmNzdihkZl9zLCJEOlxcVGltZVNlcmllc19UYXNrXFxhcmltYXdpdGhvdXRzZWFzb250cmVuZF9uZXcuY3N2Iiwgcm93Lm5hbWVzID0gRkFMU0UpDQoNCmBgYA0KUmVtb3ZpbmcgdHJlbmQgYW5kIHNlYXNvbmFsaXR5LCBhaWMgYW5kIGJpYyB2YWx1ZSByZWR1Y2VzIGEgbG90LCBidXQgd2hlbiB3ZSBvYnNlcnZlIGl0J3MgcHJlZGljdGlvbnMgd2Ugc2VlIHRoYXQgaXQgaGFzIG5lZ2F0aXZlIHZhbHVlcywgd2hpY2ggZG9lc24ndCBtYWtlIHNlbnNlLiBTbywgaW5zdGVhZCB3ZSBzaG91bGQgdHJ5IElOQVJJTUEgbW9kZWwgaGVyZSwgdG8gbWFrZSBzdXJlIHRoYXQgb3VyIG91dHB1dCBpcyBwb3NpdGl2ZSBvbmx5IHdoaWNoIGNhbiBiZSBkb25lIGFzIGZ1dHVyZSB3b3JrLg0KDQoNCg0KIyBIT0xUIFdJTlRFUidTIEVYUE9ORU5USUFMIFNNT09USElORyANCg0KVGhpcyBtZXRob2QgdXNlcyB0d28gcGFyYW1ldGVycywgb25lIGZvciB0aGUgb3ZlcmFsbCBzbW9vdGhpbmcgYW5kIHRoZSBvdGhlciBmb3IgdGhlIHRyZW5kIHNtb290aGluZyBlcXVhdGlvbi4gVGhlIG1ldGhvZCBpcyBhbHNvIGNhbGxlZCBkb3VibGUgZXhwb25lbnRpYWwgc21vb3RoaW5nIG9yIHRyZW5kLWVuaGFuY2VkIGV4cG9uZW50aWFsIHNtb290aGluZy5Gb3IgdGhlIGdpdmVuIGRhdGEgd2Ugb2JzZXJ2ZSB0aGUgZGF0YSB0aGUgY29tcG9uZW50IGFyZSBhZGRpdGl2ZSBoZW5jZSB3ZSBmb2xsb3cgdGhlIGFkZGl0aXZlIG1ldGhvZC4NClRoaXMgbWV0aG9kIGlzIHVzZWQgc2luY2UgdGhlIGZvcmVjYXN0IGlzIGZvciBhIHNob3J0IHBlcmlvZCBhbmQgaXQgZG9lc24ndCB3b3JrIHdlbGwgZm9yIGxvbmcgdGVybSBwcmVkaWN0aW9ucy4NCg0KDQoNCmBgYHtyIGVjaG89RkFMU0V9DQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmhvbHQgPC0gaG9sdChkYXRhXzEkbm9fb2ZfYXBwbGljYW50c19zdW0sDQogICAgICAgICAgICAgICAgICBoID0gMzApDQphdXRvcGxvdChob2x0KQ0KDQpgYGANCkhlcmUgd2Ugb2JzZXJ2ZSB0aGUgZXJyb3IgcmF0ZSBpbmNyZWFzaW5nIG92ZXIgdGltZSBhbmQgYWZ0ZXIgZGlmZmVyZW50aWF0aW9uIHRvbyB0aGUgbW9kZWwgY2FwdHVyZXMgb25seSANCg0KYGBge3IgZWNobz1GQUxTRSxpbmNsdWRlPUZBTFNFfQ0KIyByZW1vdmluZyB0aGUgdHJlbmQNCmRhdGFfMS5kaWYgPC0gZGlmZihkYXRhXzEkbm9fb2ZfYXBwbGljYW50c19zdW0pDQphdXRvcGxvdChkYXRhXzEuZGlmKQ0KICANCiMgcmVhcHBseWluZyBTRVMgb24gdGhlIGZpbHRlcmVkIGRhdGENCnNlcy5kYXRhXzEuZGlmIDwtIHNlcyhkYXRhXzEuZGlmLA0KICAgICAgICAgICAgICAgICAgICBhbHBoYSA9IC4yLCANCiAgICAgICAgICAgICAgICAgICAgaCA9IDEwMCkNCmF1dG9wbG90KHNlcy5kYXRhXzEuZGlmKQ0KYGBgDQpgYGB7cn0NCmxpYnJhcnkocGF0Y2h3b3JrKQ0KZT1hdXRvcGxvdChkYXRhXzEuZGlmKQ0KZj1hdXRvcGxvdChzZXMuZGF0YV8xLmRpZikNCmUNCmYNCmBgYA0KDQoNCmBgYHtyIGVjaG89RkFMU0V9DQpob2x0MSA8LSBob2x0KGRhdGFfMiRub19vZl9hcHBsaWNhbnRzX3N1bSwNCiAgICAgICAgICAgICAgICAgIGggPSAzMCkNCmF1dG9wbG90KGhvbHQxKQ0KYGBgDQoNCg0KDQoNCg0KDQoNCg0KIyBTQVJJTUFYIA0KU2Vhc29uYWwgQXV0by1SZWdyZXNzaXZlIEludGVncmF0ZWQgTW92aW5nIEF2ZXJhZ2Ugd2l0aCBleG9nZW5vdXMgZmFjdG9ycywgb3IgU0FSSU1BWCwgaXMgYW4gZXh0ZW5zaW9uIG9mIHRoZSBBUklNQSBjbGFzcyBvZiBtb2RlbHMuIFNBUklNQVggaGFzIHRoZSBjYXBhYmlsaXR5IHRvIGhhbmRsZSBleG9nZW5vdXMgdmFyaWFibGUgbGlrZSBob2xpZGF5cy4gV2UNCmNhbiBhbHNvIGdldCB5b3VyIG93biBkb21haW4tc3BlY2lmaWMgZmVhdHVyZXMgaWYgeW91IG5lZWQgdG8uIEluIG91ciBjYXNlLCB3ZSBjb21iaW5lZCB0aGUgb3JpZ2luYWwgZGF0YSB3aXRoIEluZGlhbiBob2xpZGF5cyBhbmQgYnVpbHQgYSBTQVJJTUFYIG1vZGVsLg0KDQoNCg0KSW5pdGlhbGx5IHRoZSBiaW5hcnkgdmFyaWFibGVzIGluIEhvbGlkYXkgY29sdW1uIHdhcyBjb252ZXJ0ZWQgdG8gMXMgYW5kIDBzIGZyb20geWVzIGFuZCBuby4NClRoaXMgZGF0YSBpcyBhZGRlZCBhcyB0aGUgZXhvZ2Vub3VzIHZhcmlhYmxlIGludG8gdGhlIEFSSU1BWCBtb2RlbCwgbWFraW5nIGl0IFNBUklNQVguV2UgdXNlIHRoZSBtZXRob2QgTWF4aW11bSBMaWtlbGlob29kIEVzdGltYXRlIHRvIG1ha2UgdGhlIHByZWRpY3Rpb25zLg0KRml0dGluZyBTQVJJTUFYIG1vZGVsIHdpdGggc2Vhc29uYWwgQVJJTUEgb3JkZXIgKDIsMiwwKSBmb3Igc2VnbWVudCAxIGFuZCAoNCwyLDApIGZvciBzZWdtZW50IDIuDQoNCkZvciBTZWdtZW50IDE6DQpgYGB7ciBtZXNzYWdlPSBGQUxTRSxpbmNsdWRlPUZBTFNFfQ0KaW5mIDwtIHRzKGRhdGFfMSRub19vZl9hcHBsaWNhbnRzX3N1bSwgc3RhcnQgPSBjKDIwMTcsNCwxKSxlbmQ9YygyMDE5LDYsNSkgLGZyZXF1ZW5jeT0zNjUpDQojaW5mDQpyaW5mIDwtIHRzKGRhdGFfMSRIb2xpZGF5LCBzdGFydCA9IGMoMjAxNyw0LDEpLGVuZD1jKDIwMTksNiw1KSAsZnJlcXVlbmN5PTM2NSkNCiNyaW5mDQojY2xhc3MocmluZikNCiNGaXR0aW5nIFNBUklNQVggbW9kZWwgd2l0aCBzZWFzb25hbCBBUklNQSBvcmRlciAoMSwwLDEpICYgZXN0aW1hdGlvbiBtZXRob2QgaXMgTUxFIChvciBNTCkgLS0+DQoNCiNpbnN0YWxsLnBhY2thZ2VzKCJUU0EiKSANCg0KbGlicmFyeShUU0EpIA0KDQptb2RlbF90cz1hcmltYXgoKGluZiksIG9yZGVyPWMoMCwxLDEpLCBzZWFzb25hbD1saXN0KG9yZGVyPWMoMCwxLDEpLCBwZXJpb2Q9MTIpLCB4cmVnPXJpbmYsIG1ldGhvZD0nTUwnKQ0KYGBgDQpgYGB7cn0NCm1vZGVsX3RzDQoNCmBgYCANCg0KQW5kIGEgQklDIHNjb3JlIG9mIDoNCg0KDQoNCg0KYGBge3J9DQpCSUMobW9kZWxfdHMpDQpgYGANCkZvciBTZWdtZW50IDINCmBgYHtyIGluY2x1ZGU9RkFMU0V9DQppaW5mIDwtIHRzKGRhdGFfMiRub19vZl9hcHBsaWNhbnRzX3N1bSwgc3RhcnQgPSBjKDIwMTcsNCwxKSxlbmQ9YygyMDE5LDYsNSkgLGZyZXF1ZW5jeT0zNjUpDQojaW5mDQpycmluZiA8LSB0cyhkYXRhXzIkSG9saWRheSwgc3RhcnQgPSBjKDIwMTcsNCwxKSxlbmQ9YygyMDE5LDYsNSkgLGZyZXF1ZW5jeT0zNjUpDQojcmluZg0KI2NsYXNzKHJpbmYpDQojRml0dGluZyBTQVJJTUFYIG1vZGVsIHdpdGggc2Vhc29uYWwgQVJJTUEgb3JkZXIgKDEsMCwxKSAmIGVzdGltYXRpb24gbWV0aG9kIGlzIE1MRSAob3IgTUwpIC0tPg0KDQojaW5zdGFsbC5wYWNrYWdlcygiVFNBIikgDQoNCmxpYnJhcnkoVFNBKSANCg0KbW9kZWxfdHMxPWFyaW1heCgoaWluZiksIG9yZGVyPWMoNCwyLDApLCBzZWFzb25hbD1saXN0KG9yZGVyPWMoNCwyLDApLCBwZXJpb2Q9MTIpLCB4cmVnPXJyaW5mLCBtZXRob2Q9J01MJykNCmBgYA0KYGBge3J9DQptb2RlbF90czENCmBgYA0KDQoNCmBgYHtyfQ0KQklDKG1vZGVsX3RzMSkNCmBgYA0KDQojIENvbmNsdXNpb24NCg0KRnJvbSB0aGUgYWJvdmUgYW5hbHlzaXMgd2UgY29uY2x1ZGUgdGhhdCB0aGUgbW9kZWwgdGhhdCBiZXR0ZXIgZXhwbGFpbnMgdGhlIGFib3ZlIGRhdGEgaXMgQVJJTUEuQnkgY2hhbmdpbmcgdGhlIHZhbHVlcyAocCxkLHEpIHdlIGNhbiBmaW5kIHRoZSBvcHRpbWFsIHZhbHVlIHVzaW5nIHRoZSBBSUMgYW5kIHRoZSBCSUMgc2NvcmUgIHdoaWNoIGNhbiBoZWxwIHVzIGluIGZvcmVjYXN0aW5nIGFjY3VyYXRlbHkuV2UgbGVhcm50IGFib3V0IGRlYWxpbmcgd2l0aCB0cmVuZCBhbmQgc2Vhc29uYWxpdHkgLlRoZSBtb2RlbCBjYW4gYmUgaW1wcm92ZWQgZnVydGhlciB1c2luZyByZXNpZHVhbCBjb21wb25lbnRzLg0KDQoNCiMgVGVhbS05IG1lbWJlcnMNCg0KPiBEb25hIFNhbSAtMjBCREEwMg0KDQo+IFByYXRpYmhhIEtTIC0gMjBCREExNQ0KDQo+IFJlYmEgU3VzYW4tIDIwQkRBMzcNCg0KPiBKYXlhc3JlZSBDLTIwQkRBNTMNCg0KPiBBYmhpaml0aCAtIDIwQkRBNjANCg0KPiBBbmFueWEgS3VtYXJpLSAyMEJEQTY4DQoNCg0KDQoNCg==